package cn.com.cifi.mars.service.impl;

import cn.com.cifi.mars.bean.bo.*;
import cn.com.cifi.mars.bean.dto.*;
import cn.com.cifi.mars.bean.vo.signPlan.*;
import cn.com.cifi.mars.bean.vo.signPlan.signOverall.MonthSignVo;
import cn.com.cifi.mars.bean.vo.signPlan.signOverall.OverallSignPlanVo;
import cn.com.cifi.mars.bean.vo.signPlan.signOverall.SupplyAndSignVo;
import cn.com.cifi.mars.bean.vo.signPlan.signOverall.YearSignVo;
import cn.com.cifi.mars.bean.vo.supply.SupplyMonthlyDetailExcelVO;
import cn.com.cifi.mars.common.exception.MsgException;
import cn.com.cifi.mars.common.redis.RedisTemplateUtil;
import cn.com.cifi.mars.constant.*;
import cn.com.cifi.mars.entity.*;
import cn.com.cifi.mars.mapper.mars.*;
import cn.com.cifi.mars.service.*;
import cn.com.cifi.mars.util.*;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.google.common.collect.Lists;
import io.swagger.annotations.ApiModelProperty;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.collections.IteratorUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.util.StreamUtils;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.*;
import java.util.stream.Collectors;
import java.util.stream.Stream;

/**
 * 供销综合分析月度表
 */
@Slf4j
@Service
public class DmDmPlanSignMonthServiceImpl extends ServiceImpl<DmDmPlanSignMonthMapper, DmDmPlanSignMonth> implements DmDmPlanSignMonthService {

    @Autowired
    private DmDmPlanSignMonthMapper dmDmPlanSignMonthMapper;
    @Autowired
    private DmDmPlanSignYearMapper dmDmPlanSignYearMapper;
    @Autowired
    private ProjectByStagesMapper projectByStagesMapper;
    @Autowired
    private SignPlanVersionService signPlanVersionService;
    @Autowired
    private SignPlanVersionMapper signPlanVersionMapper;
    @Autowired
    private SignPlanVersionSupplyDetailMapper signPlanVersionSupplyDetailMapper;
    @Autowired
    private SignPlanVersionDetailMapper signPlanVersionDetailMapper;
    @Autowired
    private ProjectService projectService;
    @Autowired
    private StageService stageService;
    @Autowired
    private StagePartNersService stagePartNersService;
    @Autowired
    private RedisTemplateUtil redisTemplateUtil;
    @Autowired
    private SysLogService sysLogService;

    int SALE_ROOM_UPDATE_SIZE = 1000;

    /**
     * 供销综合分析表底表刷新
     * @param versionIdList 要刷新的签约版本
     * @param yearMonth 刷新时间
     * @return
     */
    @Override
    public void toSign(List<String> versionIdList,String yearMonth) {
        List<DmDmPlanSignMonth> monthList = new ArrayList<>();
        List<DmDmPlanSignYear> yearList = new ArrayList<>();
        Integer yearMonthInt = Integer.valueOf(yearMonth.replace("-",""));
        Integer year = Integer.valueOf(yearMonth.split("-")[0]);

        saveLog(LogEventEnum.REFRESH,"供销综合分析表","供销综合分析表刷新","签约版本id列表:"+ versionIdList + "日期:"+ yearMonth);
        for (String versionId : versionIdList) {
            log.info("初始化供销综合分析表底表刷新:" +versionId);
            List<DmDmPlanSignMonth> monthSignList = new ArrayList<>();
            List<DmDmPlanSignYear> yearSignList = new ArrayList<>();

            List<String> versionIds = new ArrayList<>();
            versionIds.add(versionId);
            //查询分期下最早供货时间与最晚签约时间
            StartAndEndTimeBO startAndEndTimeBO = signPlanVersionService.getStartAndEndTime(versionIds);
            //数据完整性，需要初始化出当年数据
            if(startAndEndTimeBO.getStartDate().getYear() > year){
                startAndEndTimeBO.setStartDate(LocalDateTimeUtils.toLocalDateTime(yearMonth));
            }
            if(startAndEndTimeBO.getEndDate().getYear() < year){
                startAndEndTimeBO.setEndDate(LocalDateTimeUtils.toLocalDateTime(yearMonth));
            }

            //签约版本
            SignPlanVersion signPlanVersion = signPlanVersionMapper.selectByIdAndDel(versionId, IsDeleteEnum.NO.getKey());
            // 组团
            List<SignPlanVersionSupplyDetail> groupList = signPlanVersionSupplyDetailMapper.selectByType(versionId, OrgTypeEunm.ORG_GROUP.getKey(), IsDeleteEnum.NO.getKey());
            // 产品构成
            for (SignPlanVersionSupplyDetail group : groupList) {
                String pid = group.getSupplyPlanId();
                String groupId = group.getOrgId();
                // 产品构成
                List<SignPlanVersionSupplyDetail> productList = signPlanVersionSupplyDetailMapper.selectProductDetail(versionId, pid, OrgTypeEunm.ORG_PRODUCT.getKey(), null, null, IsDeleteEnum.NO.getKey());
                if (CollectionUtils.isEmpty(productList)) {
                    continue;
                }
                for (SignPlanVersionSupplyDetail product : productList) {
                    // 初始化签约供货详情查询条件
                    SignProductCodeBO signSupplyBO = new SignProductCodeBO();
                    signSupplyBO.setVersionId(product.getVersionId());
                    signSupplyBO.setPid(product.getPid());
                    signSupplyBO.setProductCode(product.getOrgCode());
                    signSupplyBO.setBusinessType(product.getBusinessType());
                    signSupplyBO.setFreeType(product.getFreeType());
                    signSupplyBO.setProType(product.getProType());
                    signSupplyBO.setIsDel(IsDeleteEnum.NO.getKey());
                    // 初始化签约详情查询条件
                    SignProductCodeBO signDetailBO = new SignProductCodeBO();
                    signDetailBO.setVersionId(product.getVersionId());
                    signDetailBO.setPid(groupId);
                    signDetailBO.setProductCode(product.getOrgCode());
                    signDetailBO.setBusinessType(product.getBusinessType());
                    signDetailBO.setFreeType(product.getFreeType());
                    signDetailBO.setProType(product.getProType());
                    signDetailBO.setIsDel(IsDeleteEnum.NO.getKey());

                    // 是否车位楼栋
                    Integer isParking = product.getIsParking();

                    OverallSignPlanVo vo = new OverallSignPlanVo();
                    vo.setId(product.getSupplyPlanId());
                    vo.setPid(product.getPid());
                    vo.setProductCode(product.getOrgCode());
                    vo.setProductName(product.getOrgName());
                    vo.setBusinessTypeName(product.getBusinessTypeName());
                    vo.setFreeTypeName(product.getFreeTypeName());
                    vo.setProTypeName(product.getProTypeName());
                    vo.setProProductCode(product.getProProductCode());
                    vo.setProProductName(product.getProProductType());
                    vo.setIsParking(isParking);

                    // 查询组团下产品构成类型供货详情列表
                    List<SignPlanVersionSupplyDetail> productSupply = signPlanVersionSupplyDetailMapper.selectSupplyPlanDetail(signSupplyBO);
                    if (CollectionUtils.isEmpty(productSupply)) {
                        continue;
                    }
                    //查询产品构成全部签约详情数据
                    List<SignPlanVersionDetail> productSignList = signPlanVersionDetailMapper.selectSignDetail(signDetailBO);

                    //计算产品构成月度全盘签约
                    List<DmDmPlanSignMonth> monthSigns = getDmDmPlanSignMonthList(productSupply, productSignList,startAndEndTimeBO, isParking);
                    //计算产品构成年度全盘签约
                    List<DmDmPlanSignYear> yearSigns = getDmDmPlanSignYearList(monthSigns,productSupply,productSignList,startAndEndTimeBO,isParking);

                    monthSignList.addAll(monthSigns);
                    yearSignList.addAll(yearSigns);
                }
                yearSignList.stream().forEach(s->s.setVersionId(versionId));
            }

            //查询项目上一层级城市公司
            ProjectByStagesDto cityCompany = projectByStagesMapper.selectOrgParent(signPlanVersion.getProjectId());
            //查询城市公司上一层级事业部
            ProjectByStagesDto businessDivision = projectByStagesMapper.selectOrgParent(cityCompany.getOrgdepid());

            MdmProject mdmProject = projectService.selectByProId(signPlanVersion.getProjectId());
            MdmStage mdmStage = stageService.selectById(signPlanVersion.getProjectfId());
            StagePartNers stagePartners = stagePartNersService.getStagePartnersByProjectFid(signPlanVersion.getProjectfId());
            DmDmValueReport dmDmValueReport = signPlanVersionMapper.selectDmValueReportByStageId(signPlanVersion.getProjectfId(),yearMonth);
            //数据补充(项目id、项目名称、分期名称、分期编码、旭辉权益比例、营销操盘方式、是否并表、现房销售)
            for (DmDmPlanSignMonth monthSign : monthSignList){
                monthSign.setCityCompanyName(cityCompany.getOrgname());
                monthSign.setCityCompanyId(cityCompany.getOrgdepid());
                monthSign.setBusinessDivisionName(businessDivision.getOrgname());
                monthSign.setBusinessDivisionId(businessDivision.getOrgdepid());
                monthSign.setProjectId(mdmProject.getProjectId());
                monthSign.setProjectCode(mdmProject.getProjectCode());
                monthSign.setProjectName(mdmProject.getProjectName());
                monthSign.setProjectfId(mdmStage.getProjectFid());
                monthSign.setStageName(mdmStage.getStageName());
                monthSign.setStageCode(mdmStage.getStageCode());
                monthSign.setEquityRatio(NumberUtils.accuracyBigDecimal(stagePartners.getEquityRatio(),2).toString());
                monthSign.setOpmarketing(stagePartners.getIsOpMarketing());
                monthSign.setIsAndTable(stagePartners.getPartNerIsAndTable() == null ? 0 : Integer.valueOf(stagePartners.getPartNerIsAndTable()));
                if(null != dmDmValueReport){
                    monthSign.setIsFirstOpen(dmDmValueReport.getIsFirstOpen());
                    monthSign.setIsContinueOpen(dmDmValueReport.getIsContinueOpen());
                    monthSign.setExistingHouses(dmDmValueReport.getIsExistRoomSale());
                }
            }
            yearSignList.forEach(s->s.setProjectId(signPlanVersion.getProjectId()));
            monthList.addAll(monthSignList);
            yearList.addAll(yearSignList);
        }

        monthList.stream().forEach(s->s.setSnapshootYearMonth(yearMonthInt));
        yearList.stream().forEach(s->s.setSnapshootYearMonth(yearMonthInt));


        //批量插入一次1000条
        if(CollectionUtils.isNotEmpty(monthList)){
            List<List> subList = ListUtils.getSubList(monthList, SALE_ROOM_UPDATE_SIZE);
            for (List list : subList) {
                List<DmDmPlanSignMonth> insertList = (List<DmDmPlanSignMonth>) list;
                dmDmPlanSignMonthMapper.insertList(insertList);
            }
        }

        if(CollectionUtils.isNotEmpty(yearList)){
            List<List> subList = ListUtils.getSubList(yearList, SALE_ROOM_UPDATE_SIZE);
            for (List list : subList) {
                List<DmDmPlanSignYear> insertList = (List<DmDmPlanSignYear>) list;
                dmDmPlanSignYearMapper.insertList(insertList);
            }
        }

    }

    /**
     * 计算产品构成月度全盘签约
     *
     * @param productSupplyList 产品构成供货详情列表
     * @param productSignList 产品构成供货签约列表
     * @param startAndEndTimeBO 起始时间与结束时间
     * @param isParking 是否车位
     * @return
     */
    private List<DmDmPlanSignMonth> getDmDmPlanSignMonthList(List<SignPlanVersionSupplyDetail> productSupplyList, List<SignPlanVersionDetail> productSignList,StartAndEndTimeBO startAndEndTimeBO, Integer isParking) {
        List<DmDmPlanSignMonth> monthSignList = new ArrayList<>();

        SignPlanVersionDetail detail = productSignList.get(0);

        //开始时间与结束时间
        LocalDateTime startDate = startAndEndTimeBO.getStartDate();
        LocalDateTime endDate = startAndEndTimeBO.getEndDate();
        for (LocalDateTime time = startDate; LocalDateTimeUtils.compareDate(time, endDate, 1); time = LocalDateTimeUtils.addDate(time)) {
            DmDmPlanSignMonth monthSign = new DmDmPlanSignMonth();
            monthSign.initialize();

            // 查询当月签约计划供货计划金额
            SignProductDetailBO monthSupplyPlanBo = signPlanVersionService.getSupplyPlanDetail(productSupplyList, time, isParking,0);
            // 查询当月签约计划供货实际金额
            SignProductDetailBO monthSupplyActualBo = signPlanVersionService.getSupplyActualDetail(productSupplyList, time, isParking);
            // 查询当月签约计划详情
            SignPlanVersionDetail monthDetail = signPlanVersionService.getSignPlanDetailByTime(productSignList, time);

            monthSign.setIsParking(isParking);
            monthSign.setSignPlanTime(time);
            if(monthDetail == null){
                monthSign.setDetailId(UUIDUtils.create().toString());
                monthSignList.add(monthSign);
                continue;
            }
            monthSign.setDetailId(monthDetail.getId());

            ////////////////////////////////////////// 月初存货///////////////////////////////////////////////////
            //<月初存货>套数/车位数
            BigDecimal earlyRoomCount = monthDetail.getEarlyRoomCount();
            // <月初存货>面积
            BigDecimal earlyRoomArea = monthDetail.getEarlyRoomArea();
            // <月初存货>套均面积
            BigDecimal earlyAvgRoomArea = monthDetail.getEarlyAvgRoomArea();
            //<月初存货>均价
            BigDecimal earlyAvgPrice = monthDetail.getEarlyAvgPrice();
            //<月初存货>金额
            BigDecimal earlySumPrice = monthDetail.getEarlySumPrice();
            //<月初存货>签约计划 套数/车位数
            BigDecimal earlySignRoomCount = monthDetail.getEarlySignRoomCount();
            //<月初存货>签约计划面积
            BigDecimal earlySignRoomArea = monthDetail.getEarlySignRoomArea();
            // <月初存货>签约计划均价
            BigDecimal earlySignAvgPrice = monthDetail.getEarlySignAvgPrice();
            //<月初存货>签约计划金额
            BigDecimal earlySignSumPrice = monthDetail.getEarlySignSumPrice();
            //<月初存货>签约实际 套数/车位数
            BigDecimal earlySignRoomCountActual = new BigDecimal(monthDetail.getEarlySignRoomCountActual());
            //<月初存货>签约实际面积
            BigDecimal earlySignRoomAreaActual = monthDetail.getEarlySignRoomAreaActual();
            //<月初存货>签约实际均价
            BigDecimal earlySignAvgPriceActual = monthDetail.getEarlySignAvgPriceActual();
            //<月初存货>签约实际金额
            BigDecimal earlySignSumPriceActual = monthDetail.getEarlySignSumPriceActual();

            ///////////////////////////////////// 月度新供///////////////////////////////////////////////
            //<月度新供>供货套数/车位数
            BigDecimal supplyRoomCount = monthDetail.getSupplyRoomCount();
            //<月度新供>供货面积
            BigDecimal supplyRoomArea = monthDetail.getSupplyRoomArea();
            //<月度新供>供货套均面积
            BigDecimal supplyAvgRoomArea = monthDetail.getSupplyAvgRoomArea();
            //<月度新供>供货均价
            BigDecimal supplyAvgPrice = monthDetail.getSupplyAvgPrice();
            //<月度新供>供货金额
            BigDecimal supplySumPrice = monthDetail.getSupplySumPrice();
            //月度新供>供货计划套数/车位数
            BigDecimal supplyRoomCountPlan = new BigDecimal(monthSupplyPlanBo.getRoomCount());
            //<月度新供>供货计划面积
            BigDecimal supplyRoomAreaPlan = monthSupplyPlanBo.getRoomArea();
            //<月度新供>供货计划套均面积
            BigDecimal supplyAvgRoomAreaPlan = monthSupplyPlanBo.getRoomAvgArea();
            //<月度新供>供货计划均价
            BigDecimal supplyAvgPricePlan = monthSupplyPlanBo.getAvgPrice();
            //<月度新供>供货计划金额
            BigDecimal supplySumPricePlan = monthSupplyPlanBo.getSumPrice();
            //<月度新供>供货实际套数/车位数
            BigDecimal supplyRoomCountActual = new BigDecimal(monthSupplyActualBo.getRoomCount());
            //<月度新供>供货实际面积
            BigDecimal supplyRoomAreaActual = monthSupplyActualBo.getRoomArea();
            //<月度新供>供货实际套均面积
            BigDecimal supplyAvgRoomAreaActual = monthSupplyActualBo.getRoomAvgArea();
            //<月度新供>供货实际均价
            BigDecimal supplyAvgPriceActual = monthSupplyActualBo.getAvgPrice();
            //<月度新供>供货实际金额
            BigDecimal supplySumPriceActual = monthSupplyActualBo.getSumPrice();
            //<月度新供>签约计划 套数/车位数
            BigDecimal supplySignRoomCount = monthDetail.getSupplySignRoomCount();
            //<月度新供>签约计划面积
            BigDecimal supplySignRoomArea = monthDetail.getSupplySignRoomArea();
            //<月度新供>签约计划均价
            BigDecimal supplySignAvgPrice = monthDetail.getSupplySignAvgPrice();
            //<月度新供>签约计划金额
            BigDecimal supplySignSumPrice = monthDetail.getSupplySignSumPrice();
            //<月度新供>签约实际 套数/车位数
            BigDecimal supplySignRoomCountActual = new BigDecimal(monthDetail.getSupplySignRoomCountActual());
            //<月度新供>签约实际面积
            BigDecimal supplySignRoomAreaActual = monthDetail.getSupplySignRoomAreaActual();
            //<月度新供>签约实际均价
            BigDecimal supplySignAvgPriceActual = monthDetail.getSupplySignAvgPriceActual();
            //<月度新供>签约实际金额
            BigDecimal supplySignSumPriceActual = monthDetail.getSupplySignSumPriceActual();

            if(isParking == WhetherEnum.YES.getKey()){
                monthSign.setEarlyRoomCountC(earlyRoomCount);
                monthSign.setEarlyRoomAreaC(earlyRoomArea);
                monthSign.setEarlyAvgRoomAreaC(earlyAvgRoomArea);
                monthSign.setEarlyAvgPriceC(earlyAvgPrice);
                monthSign.setEarlySumPriceC(earlySumPrice);
                monthSign.setEarlySignRoomCountPlanC(earlySignRoomCount);
                monthSign.setEarlySignRoomAreaPlanC(earlySignRoomArea);
                monthSign.setEarlySignAvgPricePlanC(earlySignAvgPrice);
                monthSign.setEarlySignSumPricePlanC(earlySignSumPrice);
                monthSign.setEarlySignRoomCountActualC(earlySignRoomCountActual);
                monthSign.setEarlySignRoomAreaActualC(earlySignRoomAreaActual);
                monthSign.setEarlySignAvgPriceActualC(earlySignAvgPriceActual);
                monthSign.setEarlySignSumPriceActualC(earlySignSumPriceActual);
                monthSign.setSupplyRoomCountC(supplyRoomCount);
                monthSign.setSupplyRoomAreaC(supplyRoomArea);
                monthSign.setSupplyAvgRoomAreaC(supplyAvgRoomArea);
                monthSign.setSupplyAvgPriceC(supplyAvgPrice);
                monthSign.setSupplySumPriceC(supplySumPrice);
                monthSign.setSupplyRoomCountPlanC(supplyRoomCountPlan);
                monthSign.setSupplyRoomAreaPlanC(supplyRoomAreaPlan);
                monthSign.setSupplyAvgRoomAreaPlanC(supplyAvgRoomAreaPlan);
                monthSign.setSupplyAvgPricePlanC(supplyAvgPricePlan);
                monthSign.setSupplySumPricePlanC(supplySumPricePlan);
                monthSign.setSupplyRoomCountActualC(supplyRoomCountActual);
                monthSign.setSupplyRoomAreaActualC(supplyRoomAreaActual);
                monthSign.setSupplyAvgRoomAreaActualC(supplyAvgRoomAreaActual);
                monthSign.setSupplyAvgPriceActualC(supplyAvgPriceActual);
                monthSign.setSupplySumPriceActualC(supplySumPriceActual);
                monthSign.setSupplySignRoomCountPlanC(supplySignRoomCount);
                monthSign.setSupplySignRoomAreaPlanC(supplySignRoomArea);
                monthSign.setSupplySignAvgPricePlanC(supplySignAvgPrice);
                monthSign.setSupplySignSumPricePlanC(supplySignSumPrice);
                monthSign.setSupplySignRoomCountActualC(supplySignRoomCountActual);
                monthSign.setSupplySignRoomAreaActualC(supplySignRoomAreaActual);
                monthSign.setSupplySignAvgPriceActualC(supplySignAvgPriceActual);
                monthSign.setSupplySignSumPriceActualC(supplySignSumPriceActual);
            }else {
                monthSign.setEarlyRoomCount(earlyRoomCount);
                monthSign.setEarlyRoomArea(earlyRoomArea);
                monthSign.setEarlyAvgRoomArea(earlyAvgRoomArea);
                monthSign.setEarlyAvgPrice(earlyAvgPrice);
                monthSign.setEarlySumPrice(earlySumPrice);
                monthSign.setEarlySignRoomCountPlan(earlySignRoomCount);
                monthSign.setEarlySignRoomAreaPlan(earlySignRoomArea);
                monthSign.setEarlySignAvgPricePlan(earlySignAvgPrice);
                monthSign.setEarlySignSumPricePlan(earlySignSumPrice);
                monthSign.setEarlySignRoomCountActual(earlySignRoomCountActual);
                monthSign.setEarlySignRoomAreaActual(earlySignRoomAreaActual);
                monthSign.setEarlySignAvgPriceActual(earlySignAvgPriceActual);
                monthSign.setEarlySignSumPriceActual(earlySignSumPriceActual);
                monthSign.setSupplyRoomCount(supplyRoomCount);
                monthSign.setSupplyRoomArea(supplyRoomArea);
                monthSign.setSupplyAvgRoomArea(supplyAvgRoomArea);
                monthSign.setSupplyAvgPrice(supplyAvgPrice);
                monthSign.setSupplySumPrice(supplySumPrice);
                monthSign.setSupplyRoomCountPlan(supplyRoomCountPlan);
                monthSign.setSupplyRoomAreaPlan(supplyRoomAreaPlan);
                monthSign.setSupplyAvgRoomAreaPlan(supplyAvgRoomAreaPlan);
                monthSign.setSupplyAvgPricePlan(supplyAvgPricePlan);
                monthSign.setSupplySumPricePlan(supplySumPricePlan);
                monthSign.setSupplyRoomCountActual(supplyRoomCountActual);
                monthSign.setSupplyRoomAreaActual(supplyRoomAreaActual);
                monthSign.setSupplyAvgRoomAreaActual(supplyAvgRoomAreaActual);
                monthSign.setSupplyAvgPriceActual(supplyAvgPriceActual);
                monthSign.setSupplySumPriceActual(supplySumPriceActual);
                monthSign.setSupplySignRoomCountPlan(supplySignRoomCount);
                monthSign.setSupplySignRoomAreaPlan(supplySignRoomArea);
                monthSign.setSupplySignAvgPricePlan(supplySignAvgPrice);
                monthSign.setSupplySignSumPricePlan(supplySignSumPrice);
                monthSign.setSupplySignRoomCountActual(supplySignRoomCountActual);
                monthSign.setSupplySignRoomAreaActual(supplySignRoomAreaActual);
                monthSign.setSupplySignAvgPriceActual(supplySignAvgPriceActual);
                monthSign.setSupplySignSumPriceActual(supplySignSumPriceActual);
            }

            monthSignList.add(monthSign);
        }
        //数据补充
        for(DmDmPlanSignMonth monthSign : monthSignList){
            monthSign.setVersionId(detail.getVersionId());
            monthSign.setGroupId(detail.getGroupId());
            monthSign.setGroupType(detail.getGroupType());
            monthSign.setGroupCode(detail.getGroupCode());
            monthSign.setGroupName(detail.getGroupName());
            monthSign.setProductType(detail.getProductType());
            monthSign.setProductCode(detail.getProductCode());
            monthSign.setProductName(detail.getProductName());
            monthSign.setBusinessType(detail.getBusinessType());
            monthSign.setBusinessTypeName(detail.getBusinessTypeName());
            monthSign.setFreeType(detail.getFreeType());
            monthSign.setFreeTypeName(detail.getFreeTypeName());
            monthSign.setProType(detail.getProType());
            monthSign.setProTypeName(detail.getProTypeName());
            monthSign.setProProductCode(detail.getProProductCode());
            monthSign.setProProductType(detail.getProProductType());
            monthSign.setCombinationCode(detail.getProductCode()+detail.getBusinessType()+detail.getFreeType()+detail.getProType());
        }
        return monthSignList;
    }


    /**
     * 查询当月供货计划详细数据（总是取计划）
     * @param supplyDetailList 供货详情列表
     * @param dateTime 查询时间
     * @param isParking 是否车位楼栋
     * @return
     */
    public SignProductDetailBO getSupplyPlanDetail(List<SignPlanVersionSupplyDetail> supplyDetailList, LocalDateTime dateTime, int isParking) {
        SignProductDetailBO signProductDetailBO = new SignProductDetailBO();

        String time = LocalDateTimeUtils.formatTime(dateTime, "yyyy-MM");

        Integer roomCount = 0;
        BigDecimal roomArea = BigDecimal.ZERO;
        BigDecimal roomAvgArea = BigDecimal.ZERO;
        BigDecimal avgPrice = BigDecimal.ZERO;
        BigDecimal sumPrice = BigDecimal.ZERO;

        for (SignPlanVersionSupplyDetail spvd : supplyDetailList) {
            //计划供货时间
            LocalDateTime supplyPlanDate = spvd.getSupplyDate();
            String supplyPlanTime = LocalDateTimeUtils.formatTime(supplyPlanDate, "yyyy-MM");
            if (time.equals(supplyPlanTime)) {

                if (isParking == WhetherEnum.YES.getKey()) {
                    roomCount = roomCount + spvd.getParkingNum();
                    sumPrice = sumPrice.add(spvd.getNotCommodityValue());

                } else {
                    roomCount = roomCount + spvd.getRoomNum();
                    roomArea = roomArea.add(spvd.getSaleArea());
                    sumPrice = sumPrice.add(spvd.getHouseCommodityValue());
                }
            }
        }

        if (isParking == WhetherEnum.YES.getKey()) {
            avgPrice = BigDecimalUtils.divInteger(sumPrice, roomCount, 4);
        } else {
            roomAvgArea = BigDecimalUtils.divInteger(roomArea, roomCount, 4);
            avgPrice = BigDecimalUtils.divBigDecimal(sumPrice, roomArea, 4);
        }

        signProductDetailBO.setRoomCount(roomCount);
        signProductDetailBO.setRoomAvgArea(roomAvgArea);
        signProductDetailBO.setRoomArea(roomArea);
        signProductDetailBO.setAvgPrice(avgPrice);
        signProductDetailBO.setSumPrice(sumPrice);
        return signProductDetailBO;
    }

    /**
     * 计算产品构成年度全盘签约
     * @param monthSignVoList 产品构成月度全盘签约
     * @param ssdBOList 供货详情列表
     * @param productSignList 产品构成供货签约列表
     * @param startAndEndTimeBO 开始时间与结束时间
     * @param isParking 是否车位楼栋
     * @return
     */
    private List<DmDmPlanSignYear> getDmDmPlanSignYearList(List<DmDmPlanSignMonth> monthSignList,List<SignPlanVersionSupplyDetail> productSupplyList, List<SignPlanVersionDetail> productSignList,StartAndEndTimeBO startAndEndTimeBO,int isParking) {
        List<DmDmPlanSignYear> yearSignList = new ArrayList<>();
        // 取签约供货详情,有实际取实际，无实际取计划
        List<SignSupplyDetailBO> ssdBOList = signPlanVersionService.switchSignSupplyDetailBO(productSupplyList);

        //开始时间
        LocalDateTime startDate = startAndEndTimeBO.getStartDate();
        //结束时间
        LocalDateTime endDate = startAndEndTimeBO.getEndDate();
        List<String> yearList = new ArrayList<>();
        int earliestyear = startDate.getYear();
        int latestyear = endDate.getYear();
        for (int year = earliestyear; year <= latestyear; year++) {
            yearList.add(String.valueOf(year));
        }
        for (String year : yearList){
            DmDmPlanSignYear yearSign = new DmDmPlanSignYear();
            yearSign.initialize();
            yearSign.setIsParking(isParking);
            yearSign.setYear(year);

            String yearMonth = year+"-01";
            LocalDateTime time = LocalDateTimeUtils.getEarliestMonthDate(year);

            //当年年初存货签约详情
            SignProductDetailBO yearEarlySignDetail = signPlanVersionService.getYearEalySignSumPriceActualByTime(productSignList, time,isParking);
            //当年1月签约详情
            List<DmDmPlanSignMonth> earlyMonthSigns = monthSignList.stream().filter(s -> s.getSignPlanTime().toString().contains(yearMonth)).collect(Collectors.toList());
            //当年签约详情
            List<DmDmPlanSignMonth> yearMonthSignList = monthSignList.stream().filter(s ->String.valueOf(s.getSignPlanTime().getYear()).equals(year)).collect(Collectors.toList());
            // 年度新供供货详情(有实际取月度实际供货金额，无实际取计划金额)
            SignProductDetailBO yearSupplyDetail = signPlanVersionService.getSupplyDetail(ssdBOList, time, isParking, 0);
            // 查询当年签约计划供货计划金额
            SignProductDetailBO monthSupplyPlanBo = signPlanVersionService.getSupplyPlanDetail(productSupplyList, time, isParking,1);
            ///////////////////////////////年初存货//////////////////////////////////

            //<年初存货>套数/车位数
            BigDecimal earlyNum = BigDecimal.ZERO;
            //<年初存货>面积
            BigDecimal earlyArea = BigDecimal.ZERO;
            //<年初存货>均价
            BigDecimal earlyAvgPrice = BigDecimal.ZERO;
            //<年初存货>金额
            BigDecimal earlyPrice = BigDecimal.ZERO;
            //<年初存货>签约实际 套数/车位数
            BigDecimal earlySignActualNum = BigDecimal.ZERO;
            //<年初存货>签约实际面积
            BigDecimal earlySignActualArea = BigDecimal.ZERO;
            //<年初存货>签约实际均价
            BigDecimal earlySignActualAvgPrice = BigDecimal.ZERO;
            //<年初存货>签约实际金额
            BigDecimal earlySignActualPrice = BigDecimal.ZERO;
            //<年度新供>套数/车位数
            BigDecimal supplyNum = BigDecimal.ZERO;
            //<年度新供>面积
            BigDecimal supplyArea = BigDecimal.ZERO;
            //<年度新供>均价
            BigDecimal supplyAvgPrice = BigDecimal.ZERO;
            //<年度新供>金额
            BigDecimal supplyPrice = BigDecimal.ZERO;
            //<年度新供>供货计划套数/车位数
            BigDecimal supplyPlanNum = new BigDecimal(monthSupplyPlanBo.getRoomCount());
            //<年度新供>供货计划面积
            BigDecimal supplyPlanArea = monthSupplyPlanBo.getRoomArea();
            //<年度新供>供货计划均价
            BigDecimal supplyPlanAvgPrice = monthSupplyPlanBo.getAvgPrice();
            //<年度新供>供货计划金额
            BigDecimal supplyPlanPrice = monthSupplyPlanBo.getSumPrice();
            //<年度新供>供货实际套数/车位数
            BigDecimal supplyActualNum = BigDecimal.ZERO;
            //<年度新供>供货实际面积
            BigDecimal supplyActualArea = BigDecimal.ZERO;
            //<年度新供>供货实际均价
            BigDecimal supplyActualAvgPrice = BigDecimal.ZERO;
            //<年度新供>供货实际金额
            BigDecimal supplyActualPrice = BigDecimal.ZERO;
            //<年度新供>签约实际 套数/车位数
            BigDecimal supplySignActualNum = BigDecimal.ZERO;
            //<年度新供>签约实际面积
            BigDecimal supplySignActualArea = BigDecimal.ZERO;
            //<年度新供>签约实际均价
            BigDecimal supplySignActualAvgPrice = BigDecimal.ZERO;
            //<年度新供>签约实际金额
            BigDecimal supplySignActualPrice = BigDecimal.ZERO;
            //<年度综合>可售 套数/车位数
            BigDecimal syntheticalAvailableNum = BigDecimal.ZERO;
            //<年度综合>可售面积
            BigDecimal syntheticalAvailableArea = BigDecimal.ZERO;
            //<年度综合>可售均价
            BigDecimal syntheticalAvailableAvgPrice = BigDecimal.ZERO;
            //<年度综合>可售金额
            BigDecimal syntheticalAvailablePrice = BigDecimal.ZERO;
            //<年度综合>签约计划 套数/车位数
            BigDecimal syntheticalSignPlanNum = BigDecimal.ZERO;
            //<年度综合>签约计划面积
            BigDecimal syntheticalSignPlanArea = BigDecimal.ZERO;
            //<年度综合>签约计划均价
            BigDecimal syntheticalSignPlanAvgPrice = BigDecimal.ZERO;
            //<年度综合>签约计划金额
            BigDecimal syntheticalSignPlanPrice = BigDecimal.ZERO;
            //<年度综合>签约实际 套数/车位数
            BigDecimal syntheticalSignActualNum = BigDecimal.ZERO;
            //<年度综合>签约实际面积
            BigDecimal syntheticalSignActualArea = BigDecimal.ZERO;
            //<年度综合>签约实际均价
            BigDecimal syntheticalSignActualAvgPrice = BigDecimal.ZERO;
            //<年度综合>签约实际金额
            BigDecimal syntheticalSignActualPrice = BigDecimal.ZERO;

            if(isParking == WhetherEnum.YES.getKey()){


                syntheticalSignActualNum = yearMonthSignList.stream().map(s -> s.getEarlySignRoomCountActualC().add(s.getSupplySignRoomCountActualC())).reduce(BigDecimal.ZERO,BigDecimal::add);
                syntheticalSignActualArea = yearMonthSignList.stream().map(s -> s.getEarlySignRoomAreaActualC().add(s.getSupplySignRoomAreaActualC())).reduce(BigDecimal.ZERO,BigDecimal::add);
                syntheticalSignActualPrice = yearMonthSignList.stream().map(s -> s.getEarlySignSumPriceActualC().add(s.getSupplySignSumPriceActualC())).reduce(BigDecimal.ZERO,BigDecimal::add);
                syntheticalSignActualAvgPrice = BigDecimalUtils.divBigDecimal(syntheticalSignActualPrice,syntheticalSignActualNum,4);

                ///////////////////////////////////年初存货////////////////////////////////////
                if(CollectionUtils.isNotEmpty(earlyMonthSigns)){
                    DmDmPlanSignMonth earlySignMonth = earlyMonthSigns.get(0);
                    earlyNum = earlySignMonth.getEarlyRoomCountC();
                    earlyArea = earlySignMonth.getEarlyRoomAreaC();
                    earlyAvgPrice = earlySignMonth.getEarlyAvgPriceC();
                    earlyPrice = earlySignMonth.getEarlySumPriceC();
                }
                earlySignActualNum = new BigDecimal(yearEarlySignDetail.getRoomCount());
                earlySignActualArea = yearEarlySignDetail.getRoomArea();
                earlySignActualAvgPrice = yearEarlySignDetail.getAvgPrice();
                earlySignActualPrice = yearEarlySignDetail.getSumPrice();

                ///////////////////////////////年度新供//////////////////////////////////
                supplyNum = new BigDecimal(yearSupplyDetail.getRoomCount());
                supplyArea = yearSupplyDetail.getRoomArea();
                supplyAvgPrice = yearSupplyDetail.getAvgPrice();
                supplyPrice = yearSupplyDetail.getSumPrice();
                supplyActualNum = yearMonthSignList.stream().map(s ->s.getSupplyRoomCountActualC()).reduce(BigDecimal.ZERO,BigDecimal::add);
                supplyActualArea = yearMonthSignList.stream().map(s -> s.getSupplyRoomAreaActualC()).reduce(BigDecimal.ZERO,BigDecimal::add);
                supplyActualPrice = yearMonthSignList.stream().map(s -> s.getSupplySumPriceActualC()).reduce(BigDecimal.ZERO,BigDecimal::add);
                supplyActualAvgPrice = BigDecimalUtils.divBigDecimal(supplyActualPrice,supplyActualNum,4);
                supplySignActualNum = syntheticalSignActualNum.subtract(earlySignActualNum);
                supplySignActualArea = syntheticalSignActualArea.subtract(earlySignActualArea);
                supplySignActualPrice = syntheticalSignActualPrice.subtract(earlySignActualPrice);
                supplySignActualAvgPrice = BigDecimalUtils.divBigDecimal(supplySignActualPrice,supplySignActualNum,4);

                ///////////////////////////////////年度综合////////////////////////////////////
                syntheticalAvailableNum = earlyNum.add(supplyNum);
                syntheticalAvailableArea = earlyArea.add(supplyArea);
                syntheticalAvailablePrice = earlyPrice.add(supplyPrice);
                syntheticalAvailableAvgPrice = BigDecimalUtils.divBigDecimal(syntheticalAvailablePrice,syntheticalAvailableNum,4);
                syntheticalSignPlanNum = yearMonthSignList.stream().map(s -> s.getEarlySignRoomCountPlanC().add(s.getSupplySignRoomCountPlanC())).reduce(BigDecimal.ZERO,BigDecimal::add);
                syntheticalSignPlanArea = yearMonthSignList.stream().map(s -> s.getEarlySignRoomAreaPlanC().add(s.getSupplySignRoomAreaPlanC())).reduce(BigDecimal.ZERO,BigDecimal::add);
                syntheticalSignPlanPrice = yearMonthSignList.stream().map(s -> s.getEarlySignSumPricePlanC().add(s.getSupplySignSumPricePlanC())).reduce(BigDecimal.ZERO,BigDecimal::add);
                syntheticalSignPlanAvgPrice = BigDecimalUtils.divBigDecimal(syntheticalSignPlanPrice,syntheticalSignPlanNum,4);

                yearSign.setEarlyNumC(earlyNum);
                yearSign.setEarlyAreaC(earlyArea);
                yearSign.setEarlyAvgPriceC(earlyAvgPrice);
                yearSign.setEarlyPriceC(earlyPrice);
                yearSign.setEarlySignActualNumC(earlySignActualNum);
                yearSign.setEarlySignActualAreaC(earlySignActualArea);
                yearSign.setEarlySignActualAvgPriceC(earlySignActualAvgPrice);
                yearSign.setEarlySignActualPriceC(earlySignActualPrice);
                yearSign.setSupplyNumC(supplyNum);
                yearSign.setSupplyAreaC(supplyArea);
                yearSign.setSupplyAvgPriceC(supplyAvgPrice);
                yearSign.setSupplyPriceC(supplyPrice);
                yearSign.setSupplyPlanNumC(supplyPlanNum);
                yearSign.setSupplyPlanAreaC(supplyPlanArea);
                yearSign.setSupplyPlanAvgPriceC(supplyPlanAvgPrice);
                yearSign.setSupplyPlanPriceC(supplyPlanPrice);
                yearSign.setSupplyActualNumC(supplyActualNum);
                yearSign.setSupplyActualAreaC(supplyActualArea);
                yearSign.setSupplyActualAvgPriceC(supplyActualAvgPrice);
                yearSign.setSupplyActualPriceC(supplyActualPrice);
                yearSign.setSupplySignActualNumC(supplySignActualNum);
                yearSign.setSupplySignActualAreaC(supplySignActualArea);
                yearSign.setSupplySignActualAvgPriceC(supplySignActualAvgPrice);
                yearSign.setSupplySignActualPriceC(supplySignActualPrice);
                yearSign.setSyntheticalAvailableNumC(syntheticalAvailableNum);
                yearSign.setSyntheticalAvailableAreaC(syntheticalAvailableArea);
                yearSign.setSyntheticalAvailableAvgPriceC(syntheticalAvailableAvgPrice);
                yearSign.setSyntheticalAvailablePriceC(syntheticalAvailablePrice);
                yearSign.setSyntheticalSignPlanNumC(syntheticalSignPlanNum);
                yearSign.setSyntheticalSignPlanAreaC(syntheticalSignPlanArea);
                yearSign.setSyntheticalSignPlanAvgPriceC(syntheticalSignPlanAvgPrice);
                yearSign.setSyntheticalSignPlanPriceC(syntheticalSignPlanPrice);
                yearSign.setSyntheticalSignActualNumC(syntheticalSignActualNum);
                yearSign.setSyntheticalSignActualAreaC(syntheticalSignActualArea);
                yearSign.setSyntheticalSignActualAvgPriceC(syntheticalSignActualAvgPrice);
                yearSign.setSyntheticalSignActualPriceC(syntheticalSignActualPrice);
            }else {

                syntheticalSignActualNum = yearMonthSignList.stream().map(s -> s.getEarlySignRoomCountActual().add(s.getSupplySignRoomCountActual())).reduce(BigDecimal.ZERO,BigDecimal::add);
                syntheticalSignActualArea = yearMonthSignList.stream().map(s -> s.getEarlySignRoomAreaActual().add(s.getSupplySignRoomAreaActual())).reduce(BigDecimal.ZERO,BigDecimal::add);
                syntheticalSignActualPrice = yearMonthSignList.stream().map(s -> s.getEarlySignSumPriceActual().add(s.getSupplySignSumPriceActual())).reduce(BigDecimal.ZERO,BigDecimal::add);
                syntheticalSignActualAvgPrice = BigDecimalUtils.divBigDecimal(syntheticalSignActualPrice,syntheticalSignActualArea,4);

                ///////////////////////////////////年初存货////////////////////////////////////
                if (CollectionUtils.isNotEmpty(earlyMonthSigns)) {
                    DmDmPlanSignMonth earlySignMonth = earlyMonthSigns.get(0);
                    earlyNum = earlySignMonth.getEarlyRoomCount();
                    earlyArea = earlySignMonth.getEarlyRoomArea();
                    earlyAvgPrice = earlySignMonth.getEarlyAvgPrice();
                    earlyPrice = earlySignMonth.getEarlySumPrice();
                }
                earlySignActualNum = new BigDecimal(yearEarlySignDetail.getRoomCount());
                earlySignActualArea = yearEarlySignDetail.getRoomArea();
                earlySignActualAvgPrice = yearEarlySignDetail.getAvgPrice();
                earlySignActualPrice = yearEarlySignDetail.getSumPrice();

                ///////////////////////////////年度新供//////////////////////////////////
                supplyNum = new BigDecimal(yearSupplyDetail.getRoomCount());
                supplyArea = yearSupplyDetail.getRoomArea();
                supplyAvgPrice = yearSupplyDetail.getAvgPrice();
                supplyPrice = yearSupplyDetail.getSumPrice();
                supplyActualNum = yearMonthSignList.stream().map(s ->s.getSupplyRoomCountActual()).reduce(BigDecimal.ZERO,BigDecimal::add);
                supplyActualArea = yearMonthSignList.stream().map(s -> s.getSupplyRoomAreaActual()).reduce(BigDecimal.ZERO,BigDecimal::add);
                supplyActualPrice = yearMonthSignList.stream().map(s -> s.getSupplySumPriceActual()).reduce(BigDecimal.ZERO,BigDecimal::add);
                supplyActualAvgPrice = BigDecimalUtils.divBigDecimal(supplyActualPrice,supplyActualArea,4);
                supplySignActualNum = syntheticalSignActualNum.subtract(earlySignActualNum);
                supplySignActualArea = syntheticalSignActualArea.subtract(earlySignActualArea);
                supplySignActualPrice = syntheticalSignActualPrice.subtract(earlySignActualPrice);
                supplySignActualAvgPrice = BigDecimalUtils.divBigDecimal(supplySignActualPrice,supplySignActualArea,4);

                ///////////////////////////////////年度综合////////////////////////////////////
                syntheticalAvailableNum = earlyNum.add(supplyNum);
                syntheticalAvailableArea = earlyArea.add(supplyArea);
                syntheticalAvailablePrice = earlyPrice.add(supplyPrice);
                syntheticalAvailableAvgPrice = BigDecimalUtils.divBigDecimal(syntheticalAvailablePrice,syntheticalAvailableArea,4);
                syntheticalSignPlanNum = yearMonthSignList.stream().map(s -> s.getEarlySignRoomCountPlan().add(s.getSupplySignRoomCountPlan())).reduce(BigDecimal.ZERO,BigDecimal::add);
                syntheticalSignPlanArea = yearMonthSignList.stream().map(s -> s.getEarlySignRoomAreaPlan().add(s.getSupplySignRoomAreaPlan())).reduce(BigDecimal.ZERO,BigDecimal::add);
                syntheticalSignPlanPrice = yearMonthSignList.stream().map(s -> s.getEarlySignSumPricePlan().add(s.getSupplySignSumPricePlan())).reduce(BigDecimal.ZERO,BigDecimal::add);
                syntheticalSignPlanAvgPrice = BigDecimalUtils.divBigDecimal(syntheticalSignPlanPrice,syntheticalSignPlanArea,4);

                yearSign.setEarlyNum(earlyNum);
                yearSign.setEarlyArea(earlyArea);
                yearSign.setEarlyAvgPrice(earlyAvgPrice);
                yearSign.setEarlyPrice(earlyPrice);
                yearSign.setEarlySignActualNum(earlySignActualNum);
                yearSign.setEarlySignActualArea(earlySignActualArea);
                yearSign.setEarlySignActualAvgPrice(earlySignActualAvgPrice);
                yearSign.setEarlySignActualPrice(earlySignActualPrice);
                yearSign.setSupplyNum(supplyNum);
                yearSign.setSupplyArea(supplyArea);
                yearSign.setSupplyAvgPrice(supplyAvgPrice);
                yearSign.setSupplyPrice(supplyPrice);
                yearSign.setSupplyPlanNum(supplyPlanNum);
                yearSign.setSupplyPlanArea(supplyPlanArea);
                yearSign.setSupplyPlanAvgPrice(supplyPlanAvgPrice);
                yearSign.setSupplyPlanPrice(supplyPlanPrice);
                yearSign.setSupplyActualNum(supplyActualNum);
                yearSign.setSupplyActualArea(supplyActualArea);
                yearSign.setSupplyActualAvgPrice(supplyActualAvgPrice);
                yearSign.setSupplyActualPrice(supplyActualPrice);
                yearSign.setSupplySignActualNum(supplySignActualNum);
                yearSign.setSupplySignActualArea(supplySignActualArea);
                yearSign.setSupplySignActualAvgPrice(supplySignActualAvgPrice);
                yearSign.setSupplySignActualPrice(supplySignActualPrice);
                yearSign.setSyntheticalAvailableNum(syntheticalAvailableNum);
                yearSign.setSyntheticalAvailableArea(syntheticalAvailableArea);
                yearSign.setSyntheticalAvailableAvgPrice(syntheticalAvailableAvgPrice);
                yearSign.setSyntheticalAvailablePrice(syntheticalAvailablePrice);
                yearSign.setSyntheticalSignPlanNum(syntheticalSignPlanNum);
                yearSign.setSyntheticalSignPlanArea(syntheticalSignPlanArea);
                yearSign.setSyntheticalSignPlanAvgPrice(syntheticalSignPlanAvgPrice);
                yearSign.setSyntheticalSignPlanPrice(syntheticalSignPlanPrice);
                yearSign.setSyntheticalSignActualNum(syntheticalSignActualNum);
                yearSign.setSyntheticalSignActualArea(syntheticalSignActualArea);
                yearSign.setSyntheticalSignActualAvgPrice(syntheticalSignActualAvgPrice);
                yearSign.setSyntheticalSignActualPrice(syntheticalSignActualPrice);
            }
            //数据补充(组团id、业态code,业态组合code)
            if(CollectionUtils.isNotEmpty(yearMonthSignList)) {
            	 yearSign.setGroupId(yearMonthSignList.get(0).getGroupId());
                 yearSign.setProProductCode(yearMonthSignList.get(0).getProProductCode());
                 yearSign.setCombinationCode(yearMonthSignList.get(0).getCombinationCode());
            }
           
            yearSignList.add(yearSign);
        }
        return yearSignList;
    }


    /**
     * 获取供销综合分析在线查看数据
     * @param yearMonth 历史版本时间
     * @param year      查看年份
     * @return
     */
    @Override
    public SignPlanVersionVo getSignPlanVersionVo(List<String> projectIdList, String yearMonth, String year) {
        SignPlanVersionVo vo = new SignPlanVersionVo();

        Integer yearMonthInt = Integer.valueOf(yearMonth.replace("-", ""));

        List<SignPlanVersionDetailDto> detailDtoList = new ArrayList<>();
        List<SignPlanVersionDetailDto> orgWandaGroupList;
        List<SignPlanVersionDetailDto> businessDivisionList;
        List<SignPlanVersionDetailDto> cityCompanyList;
        List<SignPlanVersionDetailDto> projectList;
        List<SignPlanVersionDetailDto> stageList = new ArrayList<>();
        List<ProjectByStagesDto> delProjectDtos = new ArrayList<>();

        long startTimeA = System.currentTimeMillis();
        //查询查询全盘供货与签约数据
        List<DmDmPlanSignMonth> supplyAndSignAllList = dmDmPlanSignMonthMapper.getOverallList(projectIdList,yearMonthInt);
        //查询指定项目集合和历史时间的数据
        List<DmDmPlanSignMonth> monthSignAllList = dmDmPlanSignMonthMapper.selectByYearAndProjectId(projectIdList, yearMonthInt,year);
        List<DmDmPlanSignYear> yearSignAllList = dmDmPlanSignYearMapper.selectByYearAndProjectId(projectIdList, yearMonthInt,year);
        long endTimeA = System.currentTimeMillis();

        if(CollectionUtils.isEmpty(yearSignAllList)){
            return vo;
        }

        long startTimeB = System.currentTimeMillis();
        //获取用户项目权限的项目id列表
        projectIdList = yearSignAllList.stream().map(s -> s.getProjectId()).distinct().collect(Collectors.toList());
        //查询项目数据
        List<ProjectByStagesDto> projectDtos = projectByStagesMapper.selectByOrgdepids(projectIdList);
        //查询项目上一层级城市公司
        List<ProjectByStagesDto> cityCompanyDtos = projectByStagesMapper.selectOrgParentList(projectIdList);
        //查询城市公司上一层级事业部
        List<ProjectByStagesDto> businessDivisionDtos = projectByStagesMapper.selectOrgParentList(cityCompanyDtos.stream().map(s -> s.getOrgdepid()).collect(Collectors.toList()));
        //查询事业部上一层级全集团
        List<ProjectByStagesDto> orgWandaGroupDtos = projectByStagesMapper.selectOrgParentList(businessDivisionDtos.stream().map(s -> s.getOrgdepid()).collect(Collectors.toList()));

        //获取全部版本id列表
        List<String> versionIdAllList = yearSignAllList.stream().map(s -> s.getVersionId()).distinct().collect(Collectors.toList());
        List<SignPlanVersion> signPlanVersionList = signPlanVersionMapper.selectByVersionIds(versionIdAllList, IsDeleteEnum.NO.getKey());
        for (ProjectByStagesDto projectDto : projectDtos) {
            List<SignPlanVersionDetailDto> projects = new ArrayList<>();
            //项目id
            String projectId = projectDto.getOrgdepid();

            //查询指定项目的数据
            List<DmDmPlanSignMonth> supplyAndSignList = supplyAndSignAllList.stream().filter(s -> s.getProjectId().equals(projectId)).collect(Collectors.toList());
            List<DmDmPlanSignYear> yearSignList = yearSignAllList.stream().filter(s -> s.getProjectId().equals(projectId)).collect(Collectors.toList());
            List<DmDmPlanSignMonth> monthSignList = monthSignAllList.stream().filter(s -> s.getProjectId().equals(projectId)).collect(Collectors.toList());

            //筛选出项目下的签约版本集合
            List<SignPlanVersion> versionList = signPlanVersionList.stream().filter(s -> projectId.equals(s.getProjectId())).collect(Collectors.toList());
            for (SignPlanVersion signPlanVersion : versionList) {
                SignPlanVersionDetailDto dto = new SignPlanVersionDetailDto();
                String versionId = signPlanVersion.getId();


                //查询指定版本数据
                List<DmDmPlanSignMonth> supplyAndSigns = supplyAndSignList.stream().filter(s -> s.getVersionId().equals(versionId)).collect(Collectors.toList());
                List<DmDmPlanSignYear> yearSigns = yearSignList.stream().filter(s -> s.getVersionId().equals(versionId)).collect(Collectors.toList());
                List<DmDmPlanSignMonth> monthSigns = monthSignList.stream().filter(s -> s.getVersionId().equals(versionId)).collect(Collectors.toList());
                if(CollectionUtils.isEmpty(monthSigns)){
                    continue;
                }

                //计算全盘供货与签约
                SupplyAndSignDto supplyAndSignDto = getSupplyAndSignDto(supplyAndSigns);
                //计算年度签约
                YearDepositNewSupplyDto yearDto = getYearDepositNewSupplyDto(yearSigns, year);
                //计算月度签约
                List<YearEarlyBottomDto> monthDtoList = getYearEarlyBottomDto(monthSigns, year);

                DmDmPlanSignMonth month = monthSigns.get(0);
                dto.setId(month.getProjectfId());
                dto.setPid(month.getProjectId());
                dto.setType(OrgTypeEunm.ORG_STAGE.getKey());
                dto.setName(month.getStageName()+ "("+ VersionUtils.getFullName(signPlanVersion) + ")");
                dto.setSupplyAndSign(supplyAndSignDto);
                dto.setYearDepositNewSupply(yearDto);
                dto.setYearEarlyBottomList(monthDtoList);
                projects.add(dto);
                stageList.add(dto);
            }
            if(CollectionUtils.isEmpty(projects)) {
                delProjectDtos.add(projectDto);
            }

        }
        projectDtos.removeAll(delProjectDtos);
        cityCompanyDtos = getOrgParentList(projectDtos, cityCompanyDtos);
        businessDivisionDtos = getOrgParentList(cityCompanyDtos, businessDivisionDtos);
        orgWandaGroupDtos = getOrgParentList(businessDivisionDtos, orgWandaGroupDtos);

        projectList = signDataSorting(projectDtos, stageList, OrgTypeEunm.ORG_PRODUCTF.getKey());
        cityCompanyList = signDataSorting(cityCompanyDtos, projectList, OrgTypeEunm.ORG_CITY_COMPANY.getKey());
        businessDivisionList = signDataSorting(businessDivisionDtos, cityCompanyList, OrgTypeEunm.ORG_BUSINESS_DIVISION.getKey());
        orgWandaGroupList = signDataSorting(orgWandaGroupDtos, businessDivisionList, OrgTypeEunm.ORG_WANDA_GROUP.getKey());
        long endTimeB = System.currentTimeMillis();

        //分期排序
        stageList.sort((a,b) ->{
            String[] aStr = a.getName().split("期");
            String[] bStr = b.getName().split("期");

            String aValue = NumberEnum.getKeyByValue(aStr[0]) == null ? "0" : NumberEnum.getKeyByValue(aStr[0]);
            String bValue = NumberEnum.getKeyByValue(bStr[0]) == null ? "0" : NumberEnum.getKeyByValue(bStr[0]);

            return aValue == null ? 1 : bValue == null ? -1 : Integer.valueOf(aValue) - Integer.valueOf(bValue);
        });


        detailDtoList.addAll(orgWandaGroupList);
        detailDtoList.addAll(businessDivisionList);
        detailDtoList.addAll(cityCompanyList);
        detailDtoList.addAll(projectList);

        detailDtoList.addAll(stageList);

        // 单位转换
        detailDtoList = signPlanVersionService.unitConversion(detailDtoList);

        List<String> timeList = dmDmPlanSignYearMapper.selectYearList(projectIdList,yearMonthInt);

        vo.setDetailList(detailDtoList);
        vo.setTimeList(timeList);
        saveLog(LogEventEnum.BROWSE,"供销综合分析表","供销综合分析在线查看","查询指定项目集合和历史时间的数据执行时间："+(float)(endTimeA - startTimeA)/1000+"s"+ ";" + "计算项目层级数据及向上汇总执行时间："+(float)(endTimeB - startTimeB)/1000+"s");
        return vo;
    }

    /**
     * 获取子集中存在的父级数据
     * @param orgdepList 子集
     * @param parentOrgList 父级
     * @return
     */
    private List<ProjectByStagesDto> getOrgParentList(List<ProjectByStagesDto> orgdepList, List<ProjectByStagesDto> parentOrgList) {
        List<String> orgdeps = orgdepList.stream().map(s -> s.getParentOrgid()).distinct().collect(Collectors.toList());
        return parentOrgList.stream().filter(s -> orgdeps.contains(s.getOrgdepid())).collect(Collectors.toList());
    }

    /**
     * 向上一层级汇总
     * @param orgTypeDetailList 层级数据
     * @param detailList        被汇总的数据集合
     * @param orgType           被汇总数据的层级
     * @return
     */
    private List<SignPlanVersionDetailDto> signDataSorting(List<ProjectByStagesDto> orgTypeDetailList, List<SignPlanVersionDetailDto> detailList, String orgType) {

        List<SignPlanVersionDetailDto> spvddList = new ArrayList<>();

        for (ProjectByStagesDto orgTypeDetail : orgTypeDetailList) {
            SignPlanVersionDetailDto spvdd = new SignPlanVersionDetailDto();

            spvdd.setId(orgTypeDetail.getOrgdepid());
            spvdd.setPid(orgTypeDetail.getParentOrgid());
            spvdd.setType(orgType);
            spvdd.setName(orgTypeDetail.getOrgname());

            // 分期供货与签约
            SupplyAndSignDto supplyAndSign = new SupplyAndSignDto();

            // 可售货值套数
            String availableNum = NumberUtils.stringInitial(2, 5);
            // 可售货值金额
            String availableAmount = NumberUtils.stringInitial(3, 4);
            // 累计已供套数
            String accumulativeSupplyNum = NumberUtils.stringInitial(2, 5);
            // 累计已供金额
            String accumulativeSupplyAmount = NumberUtils.stringInitial(3, 4);
            // 累计已售套数
            String accumulativeSoldNum = NumberUtils.stringInitial(2, 0);
            // 累计已售金额
            String accumulativeSold = NumberUtils.stringInitial(3, 4);

            // 年初存货,年度新供,年度综合
            YearDepositNewSupplyDto yearDepositNewSupply = new YearDepositNewSupplyDto();

            // 年初存货套数
            String c_earlyInventoryNum = NumberUtils.stringInitial(2, 5);
            // 年初存货金额
            String c_earlyInventoryAmount = NumberUtils.stringInitial(3, 4);
            // 年初存货签约实际套数
            String c_actualContractNum = NumberUtils.stringInitial(2, 5);
            // 年初存货签约实际金额
            String c_actualContractAmount = NumberUtils.stringInitial(3, 4);
            // 年度新供供货计划套数
            String d_supplyPlanNum = NumberUtils.stringInitial(2, 5);
            // 年度新供供货计划金额
            String d_supplyPlanAmount = NumberUtils.stringInitial(3, 4);
            // 年度新供供货实际套数
            String d_supplyPlanActualNum = NumberUtils.stringInitial(2, 5);
            // 年度新供供货实际金额
            String d_supplyPlanActualAmount = NumberUtils.stringInitial(3, 4);
            // 年度新供签约实际套数
            String d_actualContractNum = NumberUtils.stringInitial(2, 5);
            // 年度新供签约实际金额
            String d_actualContractAmount = NumberUtils.stringInitial(3, 4);
            // 年度可售套数
            String e_annualSaleNum = NumberUtils.stringInitial(2, 5);
            // 年度可售金额
            String e_annualSaleAmount = NumberUtils.stringInitial(3, 4);
            // 年度综合签约计划套数
            String e_signingPlanNum = NumberUtils.stringInitial(2, 5);
            // 年度综合签约计划金额
            String e_signingPlanAmount = NumberUtils.stringInitial(3, 4);
            // 年度综合签约实际套数
            String e_signingActualNum = NumberUtils.stringInitial(2, 5);
            // 年度综合签约实际金额
            String e_signingActualAmount = NumberUtils.stringInitial(3, 4);


            for (SignPlanVersionDetailDto spvd : detailList) {
                if (spvd.getPid().equals(spvdd.getId())) {
                    SupplyAndSignDto sasd = spvd.getSupplyAndSign();
                    YearDepositNewSupplyDto ydnsd = spvd.getYearDepositNewSupply();

                    availableNum = NumberUtils.numAdd(availableNum, sasd.getAvailableNum());
                    availableAmount = NumberUtils.priceAdd(availableAmount, sasd.getAvailableAmount());
                    accumulativeSupplyNum = NumberUtils.numAdd(accumulativeSupplyNum, sasd.getAccumulativeSupplyNum());
                    accumulativeSupplyAmount = NumberUtils.priceAdd(accumulativeSupplyAmount, sasd.getAccumulativeSupplyAmount());
                    accumulativeSoldNum = NumberUtils.numAdd(accumulativeSoldNum, sasd.getAccumulativeSoldNum());
                    accumulativeSold = NumberUtils.priceAdd(accumulativeSold, sasd.getAccumulativeSold());

                    c_earlyInventoryNum = NumberUtils.numAdd(c_earlyInventoryNum, ydnsd.getC_earlyInventoryNum());
                    c_earlyInventoryAmount = NumberUtils.priceAdd(c_earlyInventoryAmount, ydnsd.getC_earlyInventoryAmount());
                    c_actualContractNum = NumberUtils.numAdd(c_actualContractNum, ydnsd.getC_actualContractNum());
                    c_actualContractAmount = NumberUtils.priceAdd(c_actualContractAmount, ydnsd.getC_actualContractAmount());
                    d_supplyPlanNum = NumberUtils.numAdd(d_supplyPlanNum, ydnsd.getD_supplyPlanNum());
                    d_supplyPlanAmount = NumberUtils.priceAdd(d_supplyPlanAmount, ydnsd.getD_supplyPlanAmount());
                    d_supplyPlanActualNum = NumberUtils.numAdd(d_supplyPlanActualNum, ydnsd.getD_supplyPlanActualNum());
                    d_supplyPlanActualAmount = NumberUtils.priceAdd(d_supplyPlanActualAmount, ydnsd.getD_supplyPlanActualAmount());
                    d_actualContractNum = NumberUtils.numAdd(d_actualContractNum, ydnsd.getD_actualContractNum());
                    d_actualContractAmount = NumberUtils.priceAdd(d_actualContractAmount, ydnsd.getD_actualContractAmount());
                    e_annualSaleNum = NumberUtils.numAdd(e_annualSaleNum, ydnsd.getE_annualSaleNum());
                    e_annualSaleAmount = NumberUtils.priceAdd(e_annualSaleAmount, ydnsd.getE_annualSaleAmount());
                    e_signingPlanNum = NumberUtils.numAdd(e_signingPlanNum, ydnsd.getE_signingPlanNum());
                    e_signingPlanAmount = NumberUtils.priceAdd(e_signingPlanAmount, ydnsd.getE_signingPlanAmount());
                    e_signingActualNum = NumberUtils.numAdd(e_signingActualNum, ydnsd.getE_signingActualNum());
                    e_signingActualAmount = NumberUtils.priceAdd(e_signingActualAmount, ydnsd.getE_signingActualAmount());
                }
            }
            supplyAndSign.setAvailableNum(availableNum);
            supplyAndSign.setAvailableAmount(availableAmount);
            supplyAndSign.setAccumulativeSupplyNum(accumulativeSupplyNum);
            supplyAndSign.setAccumulativeSupplyAmount(accumulativeSupplyAmount);
            supplyAndSign.setAccumulativeSoldNum(accumulativeSoldNum);
            supplyAndSign.setAccumulativeSold(accumulativeSold);
            supplyAndSign.calculatedPercentage();
            spvdd.setSupplyAndSign(supplyAndSign);

            yearDepositNewSupply.setC_earlyInventoryNum(c_earlyInventoryNum);
            yearDepositNewSupply.setC_earlyInventoryAmount(c_earlyInventoryAmount);
            yearDepositNewSupply.setC_actualContractNum(c_actualContractNum);
            yearDepositNewSupply.setC_actualContractAmount(c_actualContractAmount);
            yearDepositNewSupply.setD_supplyPlanNum(d_supplyPlanNum);
            yearDepositNewSupply.setD_supplyPlanAmount(d_supplyPlanAmount);
            yearDepositNewSupply.setD_supplyPlanActualNum(d_supplyPlanActualNum);
            yearDepositNewSupply.setD_supplyPlanActualAmount(d_supplyPlanActualAmount);
            yearDepositNewSupply.setD_actualContractNum(d_actualContractNum);
            yearDepositNewSupply.setD_actualContractAmount(d_actualContractAmount);
            yearDepositNewSupply.setE_signingPlanNum(e_signingPlanNum);
            yearDepositNewSupply.setE_signingPlanAmount(e_signingPlanAmount);
            yearDepositNewSupply.setE_signingActualNum(e_signingActualNum);
            yearDepositNewSupply.setE_signingActualAmount(e_signingActualAmount);
            yearDepositNewSupply.setE_annualSaleNum(e_annualSaleNum);
            yearDepositNewSupply.setE_annualSaleAmount(e_annualSaleAmount);
            yearDepositNewSupply.calculatedPercentage();
            spvdd.setYearDepositNewSupply(yearDepositNewSupply);

            ////////////////////////////////////// 月份数据汇总///////////////////////////////////////////
            // 月初存货,月度新供,月度综合
            List<YearEarlyBottomDto> yearEarlyBottomList = new ArrayList<>();
            int monthName = 1;
            for (int i = 0; i < 12; i++) {
                YearEarlyBottomDto yearEarlyBottomDto = new YearEarlyBottomDto();
                yearEarlyBottomDto.setName(String.valueOf(monthName++));
                // 月初存货套数
                String f_monthlyInventoryNum = NumberUtils.stringInitial(2, 5);
                // 月初存货金额
                String f_monthlyInventoryAmount = NumberUtils.stringInitial(3, 4);
                // 月初存货签约计划套数
                String f_signingPlanNum = NumberUtils.stringInitial(2, 5);
                // 月初存货签约计划金额
                String f_signingPlanAmount = NumberUtils.stringInitial(3, 4);
                // 月初存货签约实际套数
                String f_signingActualNum = NumberUtils.stringInitial(2, 5);
                // 月初存货签约实际金额
                String f_signingActualAmount = NumberUtils.stringInitial(3, 4);
                // 月新供供货计划套数
                String g_supplyPlanNum = NumberUtils.stringInitial(2, 5);
                // 月新供供货计划金额
                String g_supplyPlanAmount = NumberUtils.stringInitial(3, 4);
                // 月新供供货实际套数
                String g_supplyPlanActualNum = NumberUtils.stringInitial(2, 5);
                // 月新供供货实际金额
                String g_supplyPlanActualAmount = NumberUtils.stringInitial(3, 4);
                // 月新供签约计划套数
                String g_signingPlanNum = NumberUtils.stringInitial(2, 5);
                // 月新供签约计划金额
                String g_signingPlanAmount = NumberUtils.stringInitial(3, 4);
                // 月新供签约实际套数
                String g_signingActualNum = NumberUtils.stringInitial(2, 5);
                // 月新供签约实际金额
                String g_signingActualAmount = NumberUtils.stringInitial(3, 4);
                //<月度综合>月度可售套数
                String h_monthlyAvailableNum = NumberUtils.stringInitial(2,5);
                //<月度综合>月度可售金额
                String h_monthlyAvailableAmount = NumberUtils.stringInitial(3,4);

                // 被汇总的数据的层级是产品构成
                for (SignPlanVersionDetailDto spvd : detailList) {
                    if (spvd.getPid().equals(spvdd.getId())) {
                        List<YearEarlyBottomDto> spvdYearEarlyBottomList = spvd.getYearEarlyBottomList();

                        YearEarlyBottomDto iDto = spvdYearEarlyBottomList.get(i);

                        f_monthlyInventoryNum = NumberUtils.numAdd(f_monthlyInventoryNum, iDto.getF_monthlyInventoryNum());
                        f_monthlyInventoryAmount = NumberUtils.priceAdd(f_monthlyInventoryAmount, iDto.getF_monthlyInventoryAmount());
                        f_signingPlanNum = NumberUtils.numAdd(f_signingPlanNum, iDto.getF_signingPlanNum());
                        f_signingPlanAmount = NumberUtils.priceAdd(f_signingPlanAmount, iDto.getF_signingPlanAmount());
                        f_signingActualNum = NumberUtils.numAdd(f_signingActualNum, iDto.getF_signingActualNum());
                        f_signingActualAmount = NumberUtils.priceAdd(f_signingActualAmount, iDto.getF_signingActualAmount());
                        g_supplyPlanNum = NumberUtils.numAdd(g_supplyPlanNum, iDto.getG_supplyPlanNum());
                        g_supplyPlanAmount = NumberUtils.priceAdd(g_supplyPlanAmount, iDto.getG_supplyPlanAmount());
                        g_supplyPlanActualNum = NumberUtils.numAdd(g_supplyPlanActualNum, iDto.getG_supplyPlanActualNum());
                        g_supplyPlanActualAmount = NumberUtils.priceAdd(g_supplyPlanActualAmount, iDto.getG_supplyPlanActualAmount());
                        g_signingPlanNum = NumberUtils.numAdd(g_signingPlanNum, iDto.getG_signingPlanNum());
                        g_signingPlanAmount = NumberUtils.priceAdd(g_signingPlanAmount, iDto.getG_signingPlanAmount());
                        g_signingActualNum = NumberUtils.numAdd(g_signingActualNum, iDto.getG_signingActualNum());
                        g_signingActualAmount = NumberUtils.priceAdd(g_signingActualAmount, iDto.getG_signingActualAmount());
                        h_monthlyAvailableNum = NumberUtils.numAdd(h_monthlyAvailableNum, iDto.getH_monthlyAvailableNum());
                        h_monthlyAvailableAmount = NumberUtils.priceAdd(h_monthlyAvailableAmount, iDto.getH_monthlyAvailableAmount());
                    }
                }
                yearEarlyBottomDto.setF_monthlyInventoryNum(f_monthlyInventoryNum);
                yearEarlyBottomDto.setF_monthlyInventoryAmount(f_monthlyInventoryAmount);
                yearEarlyBottomDto.setF_signingPlanNum(f_signingPlanNum);
                yearEarlyBottomDto.setF_signingPlanAmount(f_signingPlanAmount);
                yearEarlyBottomDto.setF_signingActualNum(f_signingActualNum);
                yearEarlyBottomDto.setF_signingActualAmount(f_signingActualAmount);
                yearEarlyBottomDto.setG_supplyPlanNum(g_supplyPlanNum);
                yearEarlyBottomDto.setG_supplyPlanAmount(g_supplyPlanAmount);
                yearEarlyBottomDto.setG_supplyPlanActualNum(g_supplyPlanActualNum);
                yearEarlyBottomDto.setG_supplyPlanActualAmount(g_supplyPlanActualAmount);
                yearEarlyBottomDto.setG_signingPlanNum(g_signingPlanNum);
                yearEarlyBottomDto.setG_signingPlanAmount(g_signingPlanAmount);
                yearEarlyBottomDto.setG_signingActualNum(g_signingActualNum);
                yearEarlyBottomDto.setG_signingActualAmount(g_signingActualAmount);
                yearEarlyBottomDto.setH_monthlyAvailableNum(h_monthlyAvailableNum);
                yearEarlyBottomDto.setH_monthlyAvailableAmount(h_monthlyAvailableAmount);

                yearEarlyBottomDto.calculatedPercentage();
                yearEarlyBottomList.add(yearEarlyBottomDto);
            }
            spvdd.setYearEarlyBottomList(yearEarlyBottomList);
            spvddList.add(spvdd);
        }
        return spvddList;
    }

    /**
     * 计算月度签约
     *
     * @param monthSignList
     * @return
     */
    private List<YearEarlyBottomDto> getYearEarlyBottomDto(List<DmDmPlanSignMonth> monthSignList, String year) {
        List<YearEarlyBottomDto> monthDtoList = new ArrayList<>();
        //指定年份数据
        List<DmDmPlanSignMonth> monthSigns = monthSignList.stream().filter(s -> String.valueOf(s.getSignPlanTime().getYear()).equals(year)).collect(Collectors.toList());

        for (int i = 1; i <= 12; i++) {
            YearEarlyBottomDto monthDto = new YearEarlyBottomDto();
            int month = i;
            List<DmDmPlanSignMonth> monthSign = monthSigns.stream().filter(s -> s.getSignPlanTime().getMonthValue() == month).collect(Collectors.toList());
            monthDto.setName(String.valueOf(month));
            if (CollectionUtils.isEmpty(monthSign)) {
                //基础数据初始化
                monthDto.initialize();
                //月度综合数据计算依据百分率计算
                monthDto.calculatedPercentage();
                monthDtoList.add(monthDto);
                continue;
            }
            // 月初存货套数
            BigDecimal f_monthlyInventoryNumH = monthSign.stream().map(s -> s.getEarlyRoomCount()).reduce(BigDecimal.ZERO, BigDecimal::add);
            BigDecimal f_monthlyInventoryNumC = monthSign.stream().map(s -> s.getEarlyRoomCountC()).reduce(BigDecimal.ZERO, BigDecimal::add);
            // 月初存货金额
            BigDecimal f_monthlyInventoryAmountH = monthSign.stream().map(s -> s.getEarlySumPrice()).reduce(BigDecimal.ZERO, BigDecimal::add);
            BigDecimal f_monthlyInventoryAmountC = monthSign.stream().map(s -> s.getEarlySumPriceC()).reduce(BigDecimal.ZERO, BigDecimal::add);
            // 月初存货签约计划套数
            BigDecimal f_signingPlanNumH = monthSign.stream().map(s -> s.getEarlySignRoomCountPlan()).reduce(BigDecimal.ZERO, BigDecimal::add);
            BigDecimal f_signingPlanNumC = monthSign.stream().map(s -> s.getEarlySignRoomCountPlanC()).reduce(BigDecimal.ZERO, BigDecimal::add);
            // 月初存货签约计划金额
            BigDecimal f_signingPlanAmountH = monthSign.stream().map(s -> s.getEarlySignSumPricePlan()).reduce(BigDecimal.ZERO, BigDecimal::add);
            BigDecimal f_signingPlanAmountC = monthSign.stream().map(s -> s.getEarlySignSumPricePlanC()).reduce(BigDecimal.ZERO, BigDecimal::add);
            // 月初存货签约实际套数
            BigDecimal f_signingActualNumH = monthSign.stream().map(s -> s.getEarlySignRoomCountActual()).reduce(BigDecimal.ZERO, BigDecimal::add);
            BigDecimal f_signingActualNumC = monthSign.stream().map(s -> s.getEarlySignRoomCountActualC()).reduce(BigDecimal.ZERO, BigDecimal::add);
            // 月初存货签约实际金额
            BigDecimal f_signingActualAmountH = monthSign.stream().map(s -> s.getEarlySignSumPriceActual()).reduce(BigDecimal.ZERO, BigDecimal::add);
            BigDecimal f_signingActualAmountC = monthSign.stream().map(s -> s.getEarlySignSumPriceActualC()).reduce(BigDecimal.ZERO, BigDecimal::add);
            // 月新供供货套数
            BigDecimal g_supplyNumH = monthSign.stream().map(s -> s.getSupplyRoomCount()).reduce(BigDecimal.ZERO, BigDecimal::add);
            BigDecimal g_supplyNumC = monthSign.stream().map(s -> s.getSupplyRoomCountC()).reduce(BigDecimal.ZERO, BigDecimal::add);
            // 月新供供货金额
            BigDecimal g_supplyAmountH = monthSign.stream().map(s -> s.getSupplySumPrice()).reduce(BigDecimal.ZERO, BigDecimal::add);
            BigDecimal g_supplyAmountC = monthSign.stream().map(s -> s.getSupplySumPriceC()).reduce(BigDecimal.ZERO, BigDecimal::add);
            // 月新供供货计划套数
            BigDecimal g_supplyPlanNumH = monthSign.stream().map(s -> s.getSupplyRoomCountPlan()).reduce(BigDecimal.ZERO, BigDecimal::add);
            BigDecimal g_supplyPlanNumC = monthSign.stream().map(s -> s.getSupplyRoomCountPlanC()).reduce(BigDecimal.ZERO, BigDecimal::add);
            // 月新供供货计划金额
            BigDecimal g_supplyPlanAmountH = monthSign.stream().map(s -> s.getSupplySumPricePlan()).reduce(BigDecimal.ZERO, BigDecimal::add);
            BigDecimal g_supplyPlanAmountC = monthSign.stream().map(s -> s.getSupplySumPricePlanC()).reduce(BigDecimal.ZERO, BigDecimal::add);
            // 月新供供货实际套数
            BigDecimal g_supplyPlanActualNumH = monthSign.stream().map(s -> s.getSupplyRoomCountActual()).reduce(BigDecimal.ZERO, BigDecimal::add);
            BigDecimal g_supplyPlanActualNumC = monthSign.stream().map(s -> s.getSupplyRoomCountActualC()).reduce(BigDecimal.ZERO, BigDecimal::add);
            // 月新供供货实际金额
            BigDecimal g_supplyPlanActualAmountH = monthSign.stream().map(s -> s.getSupplySumPriceActual()).reduce(BigDecimal.ZERO, BigDecimal::add);
            BigDecimal g_supplyPlanActualAmountC = monthSign.stream().map(s -> s.getSupplySumPriceActualC()).reduce(BigDecimal.ZERO, BigDecimal::add);
            // 月新供签约计划套数
            BigDecimal g_signingPlanNumH = monthSign.stream().map(s -> s.getSupplySignRoomCountPlan()).reduce(BigDecimal.ZERO, BigDecimal::add);
            BigDecimal g_signingPlanNumC = monthSign.stream().map(s -> s.getSupplySignRoomCountPlanC()).reduce(BigDecimal.ZERO, BigDecimal::add);
            // 月新供签约计划金额
            BigDecimal g_signingPlanAmountH = monthSign.stream().map(s -> s.getSupplySignSumPricePlan()).reduce(BigDecimal.ZERO, BigDecimal::add);
            BigDecimal g_signingPlanAmountC = monthSign.stream().map(s -> s.getSupplySignSumPricePlanC()).reduce(BigDecimal.ZERO, BigDecimal::add);
            // 月新供签约实际套数
            BigDecimal g_signingActualNumH = monthSign.stream().map(s -> s.getSupplySignRoomCountActual()).reduce(BigDecimal.ZERO, BigDecimal::add);
            BigDecimal g_signingActualNumC = monthSign.stream().map(s -> s.getSupplySignRoomCountActualC()).reduce(BigDecimal.ZERO, BigDecimal::add);
            // 月新供签约实际金额
            BigDecimal g_signingActualAmountH = monthSign.stream().map(s -> s.getSupplySignSumPriceActual()).reduce(BigDecimal.ZERO, BigDecimal::add);
            BigDecimal g_signingActualAmountC = monthSign.stream().map(s -> s.getSupplySignSumPriceActualC()).reduce(BigDecimal.ZERO, BigDecimal::add);

            String g_supplyNum = BigDecimalUtils.houseAddParking(g_supplyNumH, g_supplyNumC, "num");
            String g_supplyAmount = BigDecimalUtils.houseAddParking(g_supplyAmountH, g_supplyAmountC, "amount");

            monthDto.setF_monthlyInventoryNum(BigDecimalUtils.houseAddParking(f_monthlyInventoryNumH, f_monthlyInventoryNumC, "num"));
            monthDto.setF_monthlyInventoryAmount(BigDecimalUtils.houseAddParking(f_monthlyInventoryAmountH, f_monthlyInventoryAmountC, "amount"));
            monthDto.setF_signingPlanNum(BigDecimalUtils.houseAddParking(f_signingPlanNumH, f_signingPlanNumC, "num"));
            monthDto.setF_signingPlanAmount(BigDecimalUtils.houseAddParking(f_signingPlanAmountH, f_signingPlanAmountC, "amount"));
            monthDto.setF_signingActualNum(BigDecimalUtils.houseAddParking(f_signingActualNumH, f_signingActualNumC, "num"));
            monthDto.setF_signingActualAmount(BigDecimalUtils.houseAddParking(f_signingActualAmountH, f_signingActualAmountC, "amount"));
            monthDto.setG_supplyPlanNum(BigDecimalUtils.houseAddParking(g_supplyPlanNumH, g_supplyPlanNumC, "num"));
            monthDto.setG_supplyPlanAmount(BigDecimalUtils.houseAddParking(g_supplyPlanAmountH, g_supplyPlanAmountC, "amount"));
            monthDto.setG_supplyPlanActualNum(BigDecimalUtils.houseAddParking(g_supplyPlanActualNumH, g_supplyPlanActualNumC, "num"));
            monthDto.setG_supplyPlanActualAmount(BigDecimalUtils.houseAddParking(g_supplyPlanActualAmountH, g_supplyPlanActualAmountC, "amount"));
            monthDto.setG_signingPlanNum(BigDecimalUtils.houseAddParking(g_signingPlanNumH, g_signingPlanNumC, "num"));
            monthDto.setG_signingPlanAmount(BigDecimalUtils.houseAddParking(g_signingPlanAmountH, g_signingPlanAmountC, "amount"));
            monthDto.setG_signingActualNum(BigDecimalUtils.houseAddParking(g_signingActualNumH, g_signingActualNumC, "num"));
            monthDto.setG_signingActualAmount(BigDecimalUtils.houseAddParking(g_signingActualAmountH, g_signingActualAmountC, "amount"));
            monthDto.setH_monthlyAvailableNum(NumberUtils.numAdd(monthDto.getF_monthlyInventoryNum(),g_supplyNum));
            monthDto.setH_monthlyAvailableAmount(NumberUtils.priceAdd(monthDto.getF_monthlyInventoryAmount(),g_supplyAmount));

            //月度综合数据计算依据百分率计算
            monthDto.calculatedPercentage();
            monthDtoList.add(monthDto);
        }
        return monthDtoList;
    }


    /**
     * 计算年度签约
     *
     * @param yearSignList
     * @return
     */
    private YearDepositNewSupplyDto getYearDepositNewSupplyDto(List<DmDmPlanSignYear> yearSignList, String year) {
        YearDepositNewSupplyDto yearDto = new YearDepositNewSupplyDto();

        //指定年份数据
        List<DmDmPlanSignYear> yearSigns = yearSignList.stream().filter(s -> s.getYear().equals(year)).collect(Collectors.toList());

        //年初存货套数
        BigDecimal c_earlyInventoryNum = yearSigns.stream().map(s -> s.getEarlyNum()).reduce(BigDecimal.ZERO, BigDecimal::add);
        BigDecimal c_earlyInventoryNumC = yearSigns.stream().map(s -> s.getEarlyNumC()).reduce(BigDecimal.ZERO, BigDecimal::add);
        //年初存货金额
        BigDecimal c_earlyInventoryAmount = yearSigns.stream().map(s -> s.getEarlyPrice()).reduce(BigDecimal.ZERO, BigDecimal::add);
        BigDecimal c_earlyInventoryAmountC = yearSigns.stream().map(s -> s.getEarlyPriceC()).reduce(BigDecimal.ZERO, BigDecimal::add);
        //年初存货实际签约套数
        BigDecimal c_actualContractNum = yearSigns.stream().map(s -> s.getEarlySignActualNum()).reduce(BigDecimal.ZERO, BigDecimal::add);
        BigDecimal c_actualContractNumC = yearSigns.stream().map(s -> s.getEarlySignActualNumC()).reduce(BigDecimal.ZERO, BigDecimal::add);
        //年初存货实际签约金额
        BigDecimal c_actualContractAmount = yearSigns.stream().map(s -> s.getEarlySignActualPrice()).reduce(BigDecimal.ZERO, BigDecimal::add);
        BigDecimal c_actualContractAmountC = yearSigns.stream().map(s -> s.getEarlySignActualPriceC()).reduce(BigDecimal.ZERO, BigDecimal::add);
        //年度新供供货计划套数
        BigDecimal d_supplyPlanNum = yearSigns.stream().map(s -> s.getSupplyPlanNum()).reduce(BigDecimal.ZERO, BigDecimal::add);
        BigDecimal d_supplyPlanNumC = yearSigns.stream().map(s -> s.getSupplyPlanNumC()).reduce(BigDecimal.ZERO, BigDecimal::add);
        //年度新供供货计划金额
        BigDecimal d_supplyPlanAmount = yearSigns.stream().map(s -> s.getSupplyPlanPrice()).reduce(BigDecimal.ZERO, BigDecimal::add);
        BigDecimal d_supplyPlanAmountC = yearSigns.stream().map(s -> s.getSupplyPlanPriceC()).reduce(BigDecimal.ZERO, BigDecimal::add);
        //年度新供供货实际套数
        BigDecimal d_supplyPlanActualNum = yearSigns.stream().map(s -> s.getSupplyActualNum()).reduce(BigDecimal.ZERO, BigDecimal::add);
        BigDecimal d_supplyPlanActualNumC = yearSigns.stream().map(s -> s.getSupplyActualNumC()).reduce(BigDecimal.ZERO, BigDecimal::add);
        //年度新供供货实际金额
        BigDecimal d_supplyPlanActualAmount = yearSigns.stream().map(s -> s.getSupplyActualPrice()).reduce(BigDecimal.ZERO, BigDecimal::add);
        BigDecimal d_supplyPlanActualAmountC = yearSigns.stream().map(s -> s.getSupplyActualPriceC()).reduce(BigDecimal.ZERO, BigDecimal::add);
        //年度新供实际签约套数
        BigDecimal d_actualContractNum = yearSigns.stream().map(s -> s.getSupplySignActualNum()).reduce(BigDecimal.ZERO, BigDecimal::add);
        BigDecimal d_actualContractNumC = yearSigns.stream().map(s -> s.getSupplySignActualNumC()).reduce(BigDecimal.ZERO, BigDecimal::add);
        //年度新供实际签约金额
        BigDecimal d_actualContractAmount = yearSigns.stream().map(s -> s.getSupplySignActualPrice()).reduce(BigDecimal.ZERO, BigDecimal::add);
        BigDecimal d_actualContractAmountC = yearSigns.stream().map(s -> s.getSupplySignActualPriceC()).reduce(BigDecimal.ZERO, BigDecimal::add);
        //年度综合年度可售套数
        BigDecimal e_annualSaleNum = yearSigns.stream().map(s -> s.getSyntheticalAvailableNum()).reduce(BigDecimal.ZERO, BigDecimal::add);
        BigDecimal e_annualSaleNumC = yearSigns.stream().map(s -> s.getSyntheticalAvailableNumC()).reduce(BigDecimal.ZERO, BigDecimal::add);
        //年度综合年度可售金额
        BigDecimal e_annualSaleAmount = yearSigns.stream().map(s -> s.getSyntheticalAvailablePrice()).reduce(BigDecimal.ZERO, BigDecimal::add);
        BigDecimal e_annualSaleAmountC = yearSigns.stream().map(s -> s.getSyntheticalAvailablePriceC()).reduce(BigDecimal.ZERO, BigDecimal::add);
        //年度综合签约计划套数
        BigDecimal e_signingPlanNum = yearSigns.stream().map(s -> s.getSyntheticalSignPlanNum()).reduce(BigDecimal.ZERO, BigDecimal::add);
        BigDecimal e_signingPlanNumC = yearSigns.stream().map(s -> s.getSyntheticalSignPlanNumC()).reduce(BigDecimal.ZERO, BigDecimal::add);
        //年度综合签约计划金额
        BigDecimal e_signingPlanAmount = yearSigns.stream().map(s -> s.getSyntheticalSignPlanPrice()).reduce(BigDecimal.ZERO, BigDecimal::add);
        BigDecimal e_signingPlanAmountC = yearSigns.stream().map(s -> s.getSyntheticalSignPlanPriceC()).reduce(BigDecimal.ZERO, BigDecimal::add);
        //年度综合签约实际套数
        BigDecimal e_signingActualNum = yearSigns.stream().map(s -> s.getSyntheticalSignActualNum()).reduce(BigDecimal.ZERO, BigDecimal::add);
        BigDecimal e_signingActualNumC = yearSigns.stream().map(s -> s.getSyntheticalSignActualNumC()).reduce(BigDecimal.ZERO, BigDecimal::add);
        //年度综合签约实际金额
        BigDecimal e_signingActualAmount = yearSigns.stream().map(s -> s.getSyntheticalSignActualPrice()).reduce(BigDecimal.ZERO, BigDecimal::add);
        BigDecimal e_signingActualAmountC = yearSigns.stream().map(s -> s.getSyntheticalSignActualPriceC()).reduce(BigDecimal.ZERO, BigDecimal::add);

        yearDto.setC_earlyInventoryNum(BigDecimalUtils.houseAddParking(c_earlyInventoryNum, c_earlyInventoryNumC, "num"));
        yearDto.setC_earlyInventoryAmount(BigDecimalUtils.houseAddParking(c_earlyInventoryAmount, c_earlyInventoryAmountC, "amount"));
        yearDto.setC_actualContractNum(BigDecimalUtils.houseAddParking(c_actualContractNum, c_actualContractNumC, "num"));
        yearDto.setC_actualContractAmount(BigDecimalUtils.houseAddParking(c_actualContractAmount, c_actualContractAmountC, "amount"));
        yearDto.setD_supplyPlanNum(BigDecimalUtils.houseAddParking(d_supplyPlanNum, d_supplyPlanNumC, "num"));
        yearDto.setD_supplyPlanAmount(BigDecimalUtils.houseAddParking(d_supplyPlanAmount, d_supplyPlanAmountC, "amount"));
        yearDto.setD_supplyPlanActualNum(BigDecimalUtils.houseAddParking(d_supplyPlanActualNum, d_supplyPlanActualNumC, "num"));
        yearDto.setD_supplyPlanActualAmount(BigDecimalUtils.houseAddParking(d_supplyPlanActualAmount, d_supplyPlanActualAmountC, "amount"));
        yearDto.setD_actualContractNum(BigDecimalUtils.houseAddParking(d_actualContractNum, d_actualContractNumC, "num"));
        yearDto.setD_actualContractAmount(BigDecimalUtils.houseAddParking(d_actualContractAmount, d_actualContractAmountC, "amount"));
        yearDto.setE_annualSaleNum(BigDecimalUtils.houseAddParking(e_annualSaleNum, e_annualSaleNumC, "num"));
        yearDto.setE_annualSaleAmount(BigDecimalUtils.houseAddParking(e_annualSaleAmount, e_annualSaleAmountC, "amount"));
        yearDto.setE_signingPlanNum(BigDecimalUtils.houseAddParking(e_signingPlanNum, e_signingPlanNumC, "num"));
        yearDto.setE_signingPlanAmount(BigDecimalUtils.houseAddParking(e_signingPlanAmount, e_signingPlanAmountC, "amount"));
        yearDto.setE_signingActualNum(BigDecimalUtils.houseAddParking(e_signingActualNum, e_signingActualNumC, "num"));
        yearDto.setE_signingActualAmount(BigDecimalUtils.houseAddParking(e_signingActualAmount, e_signingActualAmountC, "amount"));
        //计算百分率
        yearDto.calculatedPercentage();
        return yearDto;

    }

    /**
     * 计算全盘供货与签约
     * @param monthSignList
     * @return
     */
    private SupplyAndSignDto getSupplyAndSignDto(List<DmDmPlanSignMonth> supplyAndSigns) {
        SupplyAndSignDto supplyAndSignDto = new SupplyAndSignDto();


        //可售货值>套数/车位数
        BigDecimal availableNum = supplyAndSigns.stream().map(s -> s.getSupplyRoomCount()).reduce(BigDecimal.ZERO, BigDecimal::add);
        BigDecimal availableNumC = supplyAndSigns.stream().map(s -> s.getSupplyRoomCountC()).reduce(BigDecimal.ZERO, BigDecimal::add);
        //可售货值>金额
        BigDecimal availableAmount = supplyAndSigns.stream().map(s -> s.getSupplySumPrice()).reduce(BigDecimal.ZERO, BigDecimal::add);
        BigDecimal availableAmountC = supplyAndSigns.stream().map(s -> s.getSupplySumPriceC()).reduce(BigDecimal.ZERO, BigDecimal::add);
        //累计已供>套数/车位数
        BigDecimal accumulativeSupplyNum = supplyAndSigns.stream().map(s -> s.getSupplyRoomCountActual()).reduce(BigDecimal.ZERO, BigDecimal::add);
        BigDecimal accumulativeSupplyNumC = supplyAndSigns.stream().map(s -> s.getSupplyRoomCountActualC()).reduce(BigDecimal.ZERO, BigDecimal::add);
        //累计已供>金额
        BigDecimal accumulativeSupplyAmount = supplyAndSigns.stream().map(s -> s.getSupplySumPriceActual()).reduce(BigDecimal.ZERO, BigDecimal::add);
        BigDecimal accumulativeSupplyAmountC = supplyAndSigns.stream().map(s -> s.getSupplySumPriceActualC()).reduce(BigDecimal.ZERO, BigDecimal::add);
        //累计已售>套数/车位数
        BigDecimal accumulativeSoldNum = supplyAndSigns.stream().map(s -> s.getEarlySignRoomCountActual().add(s.getSupplySignRoomCountActual())).reduce(BigDecimal.ZERO, BigDecimal::add);
        BigDecimal accumulativeSoldNumC = supplyAndSigns.stream().map(s -> s.getEarlySignRoomCountActualC().add(s.getSupplySignRoomCountActualC())).reduce(BigDecimal.ZERO, BigDecimal::add);
        //累计已售>金额
        BigDecimal accumulativeSold = supplyAndSigns.stream().map(s -> s.getEarlySignSumPriceActual().add(s.getSupplySignSumPriceActual())).reduce(BigDecimal.ZERO, BigDecimal::add);
        BigDecimal accumulativeSoldC = supplyAndSigns.stream().map(s -> s.getEarlySignSumPriceActualC().add(s.getSupplySignSumPriceActualC())).reduce(BigDecimal.ZERO, BigDecimal::add);

        supplyAndSignDto.setAvailableNum(BigDecimalUtils.houseAddParking(availableNum, availableNumC, "num"));
        supplyAndSignDto.setAvailableAmount(BigDecimalUtils.houseAddParking(availableAmount, availableAmountC, "amount"));
        supplyAndSignDto.setAccumulativeSupplyNum(BigDecimalUtils.houseAddParking(accumulativeSupplyNum, accumulativeSupplyNumC, "num"));
        supplyAndSignDto.setAccumulativeSupplyAmount(BigDecimalUtils.houseAddParking(accumulativeSupplyAmount, accumulativeSupplyAmountC, "amount"));
        supplyAndSignDto.setAccumulativeSoldNum(BigDecimalUtils.houseAddParking(accumulativeSoldNum, accumulativeSoldNumC, "num"));
        supplyAndSignDto.setAccumulativeSold(BigDecimalUtils.houseAddParking(accumulativeSold, accumulativeSoldC, "amount"));
        //计算百分率
        supplyAndSignDto.calculatedPercentage();
        return supplyAndSignDto;
    }


    /**
     * 供销综合分析表报表导出数据
     * @param projectIdList
     * @param yearMonth
     * @return
     */
    @Override
    public List<DmAnalyticalVo> dmAnalyticalExport(List<String> projectIdList, String yearMonth) {
        List<DmAnalyticalVo> voList = new ArrayList<>();

        Integer yearMonthInt = Integer.valueOf(yearMonth.replace("-", ""));
        String year = yearMonth.split("-")[0];

        //查询指定项目集合和历史时间的数据
        List<DmDmPlanSignMonth> monthSignAllList = dmDmPlanSignMonthMapper.selectByYearAndProjectId(projectIdList, yearMonthInt,year);
        List<DmDmPlanSignYear> yearSignAllList = dmDmPlanSignYearMapper.selectByYearMonthAndProjectId(projectIdList, yearMonthInt);
        projectIdList = yearSignAllList.stream().map(s ->s.getProjectId()).collect(Collectors.toSet()).stream().collect(Collectors.toList());

        //汇总项目层级及以下数据
        List<DmAnalyticalVo> projectBelowVoList = getProjectDmAnalyticalVo(monthSignAllList,yearSignAllList,projectIdList,yearMonthInt);

        //筛选项目层级的数据
        List<DmAnalyticalVo> projectVoList = projectBelowVoList.stream().filter(s -> s.getType().equals("project")).collect(Collectors.toList());
        Map<String, Map<String, List<DmAnalyticalVo>>> projectVoListMap = projectVoList.stream()
                .collect(Collectors.groupingBy(s -> s.getBusinessDivisionId(), Collectors.groupingBy(s -> s.getCityCompanyId())));

        Map<String, List<DmAnalyticalVo>> cityCompanyVoListMap = projectVoListMap.entrySet().stream()
                .collect(Collectors.toMap(s -> s.getKey(), s -> s.getValue()
                        .entrySet().stream()
                        .map(s1 -> dmAnalyticalSorting(s1.getValue(), "cityCompany")).collect(Collectors.toList())));
        //城市公司数据列表
        List<DmAnalyticalVo> cityCompanyVoList = cityCompanyVoListMap.entrySet().stream().flatMap(s -> s.getValue().stream().map(s1->s1)).collect(Collectors.toList());
        //区域数据列表
        List<DmAnalyticalVo> businessDivisionVoList = cityCompanyVoListMap.entrySet().stream().map(s ->  dmAnalyticalSorting(s.getValue(), "businessDivision")).collect(Collectors.toList());
        //集团数据
        DmAnalyticalVo wandaGroupVo = dmAnalyticalSorting(businessDivisionVoList, OrgTypeEunm.ORG_WANDA_GROUP.getKey());

        voList.addAll(businessDivisionVoList);
        voList.addAll(cityCompanyVoList);
        voList.addAll(projectBelowVoList);

        //排序
        List<DmAnalyticalVo> sortList = sortList(voList);
        sortList.add(0,wandaGroupVo);
        return sortList;
    }

    /**
     * 汇总供销分析表中项目层级及以下数据
     * @param monthSignList 月度数据列表
     * @param yearSignList 年度数据列表
     * @param projectIdList 项目id列表
     * @param yearMonth 数据归属时间
     * @return
     */
    @Override
    public List<DmAnalyticalVo> getProjectDmAnalyticalVo(List<DmDmPlanSignMonth> monthSignList,List<DmDmPlanSignYear> yearSignList, List<String> projectIdList,Integer yearMonth){
        List<DmAnalyticalVo> projectVoList = new ArrayList<>();
        List<DmAnalyticalVo> stageVoList = new ArrayList<>();
        List<DmAnalyticalVo> proProductVoList = new ArrayList<>();
        List<DmAnalyticalVo> combinationVoList = new ArrayList<>();

        String year = yearMonth.toString().substring(0,4);
        List<DmAnalyticalVo> projectVos = new ArrayList<>();
        for (String projectId : projectIdList){
            List<DmAnalyticalVo> stageVos = new ArrayList<>();

            //查询指定项目的数据
            List<DmDmPlanSignYear> projectYearSignList = yearSignList.stream().filter(s -> s.getProjectId().equals(projectId)).collect(Collectors.toList());
            List<DmDmPlanSignMonth> projectMonthSignList = monthSignList.stream().filter(s -> s.getProjectId().equals(projectId)).collect(Collectors.toList());
            if(CollectionUtils.isEmpty(projectYearSignList)){
                continue;
            }
            //筛选出版本id集合
            Set<String> versionIdList = projectYearSignList.stream().map(s -> s.getVersionId()).collect(Collectors.toSet());
            for (String versionId : versionIdList) {
                List<DmAnalyticalVo> proProductVos = new ArrayList<>();
                //查询指定版本数据
                List<DmDmPlanSignYear> versionYearSignList = projectYearSignList.stream().filter(s -> s.getVersionId().equals(versionId)).collect(Collectors.toList());
                List<DmDmPlanSignMonth> versionMonthSignList = projectMonthSignList.stream().filter(s -> s.getVersionId().equals(versionId)).collect(Collectors.toList());
                //筛选出组团集合
                Set<String> groupList =  versionYearSignList.stream().map(s -> s.getGroupId()).collect(Collectors.toSet());
                for (String groupId : groupList){
                    //查询指定组团数据
                    List<DmDmPlanSignYear> groupYearSignList = versionYearSignList.stream().filter(s -> s.getGroupId().equals(groupId)).collect(Collectors.toList());
                    List<DmDmPlanSignMonth> groupMonthSignList = versionMonthSignList.stream().filter(s -> s.getGroupId().equals(groupId)).collect(Collectors.toList());

                    //筛选出业态code集合
                    Set<String> proProductCodeList = groupYearSignList.stream().map(s -> s.getProProductCode()).collect(Collectors.toSet());
                    for (String proProductCode : proProductCodeList) {
                        List<DmAnalyticalVo> combinationVos = new ArrayList<>();
                        //查询指定业态数据
                        List<DmDmPlanSignYear> proYearSignList = groupYearSignList.stream().filter(s -> s.getProProductCode().equals(proProductCode)).collect(Collectors.toList());
                        List<DmDmPlanSignMonth> proMonthSignList = groupMonthSignList.stream().filter(s -> s.getProProductCode().equals(proProductCode)).collect(Collectors.toList());
                        //筛选出业态组合code集合
                        Set<String> combinationCodeList = proYearSignList.stream().map(s -> s.getCombinationCode()).collect(Collectors.toSet());
                        for (String combinationCode : combinationCodeList) {

                            //查询指定业态数据
                            List<DmDmPlanSignYear> combinationYearSignList = proYearSignList.stream().filter(s -> s.getCombinationCode().equals(combinationCode)).collect(Collectors.toList());
                            List<DmDmPlanSignMonth> combinationMonthSignList = proMonthSignList.stream().filter(s -> s.getCombinationCode().equals(combinationCode)).collect(Collectors.toList());

                            DmAnalyticalVo combinationVo = getDmAnalyticalVo(combinationYearSignList,combinationMonthSignList,year);
                            combinationVos.add(combinationVo);
                        }
                        combinationVoList.addAll(combinationVos);
                        List<SignCascaderBO> proProductCascader =  toSignCascaderBO(proProductCode,proMonthSignList,"proProduct");
                        List<DmAnalyticalVo> proProductVo = dmAnalyticalSorting(proProductCascader,combinationVos,"proProduct");
                        proProductVos.addAll(proProductVo);
                    }
                }
                proProductVoList.addAll(proProductVos);
                List<SignCascaderBO> stageCascaderList =  toSignCascaderBO(versionId,versionMonthSignList,"stage");
                List<DmAnalyticalVo> stageVo = dmAnalyticalSorting(stageCascaderList,proProductVos,"stage");
                stageVos.addAll(stageVo);
            }
            stageVoList.addAll(stageVos);
            List<SignCascaderBO> projectCascaderList =  toSignCascaderBO(projectId,projectMonthSignList,"project");
            List<DmAnalyticalVo> projectVo = dmAnalyticalSorting(projectCascaderList,stageVos,"project");
            projectVos.addAll(projectVo);
        }

        projectVoList.addAll(projectVos);
        projectVoList.addAll(stageVoList);
        projectVoList.addAll(proProductVoList);
        projectVoList.addAll(combinationVoList);

        return projectVoList;
    }

    private DmAnalyticalVo dmAnalyticalSorting(List<DmAnalyticalVo> dmAnalyticalVoList, String type) {
        DmAnalyticalVo vo = new DmAnalyticalVo();
        DmAnalyticalVo dmAnalytical = dmAnalyticalVoList.get(0);
        if(type.equals("cityCompany")){
            vo.setId(dmAnalytical.getCityCompanyId());
            vo.setPid(dmAnalytical.getBusinessDivisionId());
            vo.setType(type);
            vo.setCityCompanyName(dmAnalytical.getCityCompanyName());
            vo.setBusinessDivisionName(dmAnalytical.getBusinessDivisionName());
        }else if(type.equals("businessDivision")){
            vo.setId(dmAnalytical.getCityCompanyId());
            vo.setPid("00000001");
            vo.setBusinessDivisionName(dmAnalytical.getBusinessDivisionName());
        }else if(type.equals("wanda_group")){
            vo.setId("00000001");
            vo.setPid("0");
            vo.setBusinessDivisionName("全部");
        }

        int isParking = dmAnalytical.getIsParking();
        //当年以前签约
        PastYearVo pastYearVo = pastYearVoSummarization(dmAnalyticalVoList,type,isParking);
        //月度签约
        List<MonthSignVo> monthSignVoList = monthSignVoSummarization(dmAnalyticalVoList,type,isParking);
        //年度签约
        YearSignVo yearSignVo = yearSignVoSummarization(dmAnalyticalVoList,type,isParking);
        //季度签约
        List<QuarterSignVo> quarterSignVo = quarterSignVoSummarization(dmAnalyticalVoList,type,isParking);
        //年度合计签约
        List<YearTotalVo> yearTotalVo = yearTotalVoSummarization(dmAnalyticalVoList,type,isParking);
        vo.setPastYearVo(pastYearVo);
        vo.setMonthSignVo(monthSignVoList);
        vo.setYearSignVo(yearSignVo);
        vo.setQuarterSignVo(quarterSignVo);
        vo.setYearTotalVo(yearTotalVo);
        return vo;
    }


    private List<DmAnalyticalVo> dmAnalyticalSorting(List<SignCascaderBO> cascaderList, List<DmAnalyticalVo> dmAnalyticalVoList, String type) {
        List<DmAnalyticalVo> voList = new ArrayList<>();

        for (SignCascaderBO cascader : cascaderList){
            DmAnalyticalVo vo = new DmAnalyticalVo();
            vo.setId(cascader.getId());
            vo.setPid(cascader.getPid());
            vo.setType(type);

            List<DmAnalyticalVo> dmAnalyticalVos = dmAnalyticalVoList.stream().filter(s -> s.getPid().equals(cascader.getId())).collect(Collectors.toList());
            DmAnalyticalVo dmAnalytical = dmAnalyticalVos.get(0);
            if(type.equals("proProduct")){
                vo.setBusinessDivisionName(dmAnalytical.getBusinessDivisionName());
                vo.setBusinessDivisionId(dmAnalytical.getBusinessDivisionId());
                vo.setCityCompanyName(dmAnalytical.getCityCompanyName());
                vo.setCityCompanyId(dmAnalytical.getCityCompanyId());
                vo.setProjectName(dmAnalytical.getProjectName());
                vo.setProjectCode(dmAnalytical.getProjectCode());
                vo.setProjectId(dmAnalytical.getProjectId());
                vo.setIsFirstOpen(dmAnalytical.getIsFirstOpen());
                vo.setIsContinueOpen(dmAnalytical.getIsContinueOpen());
                vo.setStageName(dmAnalytical.getStageName());
                vo.setStageCode(dmAnalytical.getStageCode());
                vo.setEquityRatio(dmAnalytical.getEquityRatio());
                vo.setOpmarketing(dmAnalytical.getOpmarketing());
                vo.setIsAndTable(dmAnalytical.getIsAndTable());
                vo.setExistingHouses(dmAnalytical.getExistingHouses());
                vo.setGroupName(dmAnalytical.getGroupName());
                vo.setProProductName(dmAnalytical.getProProductName());
                vo.setProProductCode(dmAnalytical.getProProductCode());
                vo.setIsParking(dmAnalytical.getIsParking());
            }else if(type.equals("stage")){
                vo.setBusinessDivisionName(dmAnalytical.getBusinessDivisionName());
                vo.setBusinessDivisionId(dmAnalytical.getBusinessDivisionId());
                vo.setCityCompanyName(dmAnalytical.getCityCompanyName());
                vo.setCityCompanyId(dmAnalytical.getCityCompanyId());
                vo.setProjectName(dmAnalytical.getProjectName());
                vo.setProjectCode(dmAnalytical.getProjectCode());
                vo.setProjectId(dmAnalytical.getProjectId());
                vo.setIsFirstOpen(dmAnalytical.getIsFirstOpen());
                vo.setIsContinueOpen(dmAnalytical.getIsContinueOpen());
                vo.setStageName(dmAnalytical.getStageName());
                vo.setStageCode(dmAnalytical.getStageCode());
                vo.setEquityRatio(dmAnalytical.getEquityRatio());
                vo.setOpmarketing(dmAnalytical.getOpmarketing());
                vo.setIsAndTable(dmAnalytical.getIsAndTable());
                vo.setExistingHouses(dmAnalytical.getExistingHouses());
            }else if(type.equals("project")){
                vo.setBusinessDivisionName(dmAnalytical.getBusinessDivisionName());
                vo.setBusinessDivisionId(dmAnalytical.getBusinessDivisionId());
                vo.setCityCompanyName(dmAnalytical.getCityCompanyName());
                vo.setCityCompanyId(dmAnalytical.getCityCompanyId());
                vo.setProjectName(dmAnalytical.getProjectName());
                vo.setProjectCode(dmAnalytical.getProjectCode());
                vo.setProjectId(dmAnalytical.getProjectId());
                vo.setIsFirstOpen(dmAnalytical.getIsFirstOpen());
                vo.setIsContinueOpen(dmAnalytical.getIsContinueOpen());
            }

            int isParking = dmAnalytical.getIsParking();
            //当年以前签约
            PastYearVo pastYearVo = pastYearVoSummarization(dmAnalyticalVos,type,isParking);
            //月度签约
            List<MonthSignVo> monthSignVoList = monthSignVoSummarization(dmAnalyticalVos,type,isParking);
            //年度签约
            YearSignVo yearSignVo = yearSignVoSummarization(dmAnalyticalVos,type,isParking);
            //季度签约
            List<QuarterSignVo> quarterSignVo = quarterSignVoSummarization(dmAnalyticalVos,type,isParking);
            //年度合计签约
            List<YearTotalVo> yearTotalVo = yearTotalVoSummarization(dmAnalyticalVos,type,isParking);
            vo.setPastYearVo(pastYearVo);
            vo.setMonthSignVo(monthSignVoList);
            vo.setYearSignVo(yearSignVo);
            vo.setQuarterSignVo(quarterSignVo);
            vo.setYearTotalVo(yearTotalVo);
            voList.add(vo);
        }
        return voList;
    }

    /**
     * 年度合计签约
     * @param dmAnalyticalVoList 被汇总数据
     * @param type 汇总层级
     * @param isParking 是否车位楼栋
     * @return
     */
    private List<YearTotalVo> yearTotalVoSummarization(List<DmAnalyticalVo> dmAnalyticalVoList, String type, int isParking) {
        List<YearTotalVo> yearTotalVoList = new ArrayList<>();
        List<YearTotalVo> dataList = new ArrayList<>();
        dmAnalyticalVoList.forEach(s -> dataList.addAll(s.getYearTotalVo()));
        Set<String> yearList = dataList.stream().map(s -> s.getYear()).collect(Collectors.toSet());
        for (String year : yearList){
            YearTotalVo yearTotalVo = new YearTotalVo();
            List<YearTotalVo> yearDataList = dataList.stream().filter(s -> s.getYear().equals(year)).collect(Collectors.toList());
            //<年初存货>套数/车位数
            String earlyNum = NumberUtils.stringInitial(2,5);
            //<年初存货>面积
            String earlyArea = NumberUtils.stringInitial(1,4);
            //<年初存货>均价
            String earlyAvgPrice;
            //<年初存货>金额
            String earlyPrice = NumberUtils.stringInitial(3,4);
            //<年度新供>供货计划套数/车位数
            String supplyNum = NumberUtils.stringInitial(2,5);
            //<年度新供>供货计划面积
            String supplyArea = NumberUtils.stringInitial(1,4);
            //<年度新供>供货计划均价
            String supplyAvgPrice;
            //<年度新供>供货计划金额
            String supplyPrice = NumberUtils.stringInitial(3,4);
            //<年度可售>套数/车位数
            String availableNum = NumberUtils.stringInitial(2,5);
            //<年度可售>面积
            String availableArea = NumberUtils.stringInitial(1,4);
            //<年度可售>均价
            String availableAvgPrice;
            //<年度可售>金额
            String availablePrice = NumberUtils.stringInitial(3,4);
            //<年度签约计划>套数/车位数
            String signPlanNum = NumberUtils.stringInitial(2,5);
            //<年度签约计划>面积
            String signPlanArea = NumberUtils.stringInitial(1,4);
            //<年度签约计划>均价
            String signAvgPlanPrice;
            //<年度签约计划>金额
            String signPlanPrice = NumberUtils.stringInitial(3,4);
            //<年度综合>计划去化率
            String syntheticalPlanRemovalRate;
            if(type.equals("proProduct")){
                earlyNum = yearDataList.stream().map(s -> new BigDecimal(s.getEarlyNum())).reduce(BigDecimal.ZERO,BigDecimal::add).toString();
                earlyArea = yearDataList.stream().map(s -> new BigDecimal(s.getEarlyArea())).reduce(BigDecimal.ZERO,BigDecimal::add).toString();
                earlyPrice = yearDataList.stream().map(s -> new BigDecimal(s.getEarlyPrice())).reduce(BigDecimal.ZERO,BigDecimal::add).toString();
                supplyNum = yearDataList.stream().map(s -> new BigDecimal(s.getSupplyNum())).reduce(BigDecimal.ZERO,BigDecimal::add).toString();
                supplyArea = yearDataList.stream().map(s -> new BigDecimal(s.getSupplyArea())).reduce(BigDecimal.ZERO,BigDecimal::add).toString();
                supplyPrice = yearDataList.stream().map(s -> new BigDecimal(s.getSupplyPrice())).reduce(BigDecimal.ZERO,BigDecimal::add).toString();
                availableNum = yearDataList.stream().map(s -> new BigDecimal(s.getAvailableNum())).reduce(BigDecimal.ZERO,BigDecimal::add).toString();
                availableArea = yearDataList.stream().map(s -> new BigDecimal(s.getAvailableArea())).reduce(BigDecimal.ZERO,BigDecimal::add).toString();
                availablePrice = yearDataList.stream().map(s -> new BigDecimal(s.getAvailablePrice())).reduce(BigDecimal.ZERO,BigDecimal::add).toString();
                signPlanNum = yearDataList.stream().map(s -> new BigDecimal(s.getSignPlanNum())).reduce(BigDecimal.ZERO,BigDecimal::add).toString();
                signPlanArea = yearDataList.stream().map(s -> new BigDecimal(s.getSignPlanArea())).reduce(BigDecimal.ZERO,BigDecimal::add).toString();
                signPlanPrice = yearDataList.stream().map(s -> new BigDecimal(s.getSignPlanPrice())).reduce(BigDecimal.ZERO,BigDecimal::add).toString();

                if(isParking == WhetherEnum.YES.getKey()){
                    earlyAvgPrice = BigDecimalUtils.divBigDecimal(new BigDecimal(earlyPrice),new BigDecimal(earlyNum),4).toString();
                    supplyAvgPrice = BigDecimalUtils.divBigDecimal(new BigDecimal(supplyPrice),new BigDecimal(supplyNum),4).toString();
                    availableAvgPrice = BigDecimalUtils.divBigDecimal(new BigDecimal(availablePrice),new BigDecimal(availableNum),4).toString();
                    signAvgPlanPrice = BigDecimalUtils.divBigDecimal(new BigDecimal(signPlanPrice),new BigDecimal(signPlanNum),4).toString();
                }else {
                    earlyAvgPrice = BigDecimalUtils.divBigDecimal(new BigDecimal(earlyPrice),new BigDecimal(earlyArea),4).toString();
                    supplyAvgPrice = BigDecimalUtils.divBigDecimal(new BigDecimal(supplyPrice),new BigDecimal(supplyArea),4).toString();
                    availableAvgPrice = BigDecimalUtils.divBigDecimal(new BigDecimal(availablePrice),new BigDecimal(availableArea),4).toString();
                    signAvgPlanPrice = BigDecimalUtils.divBigDecimal(new BigDecimal(signPlanPrice),new BigDecimal(signPlanArea),4).toString();
                }
                syntheticalPlanRemovalRate = BigDecimalUtils.calculatedPercentage(new BigDecimal(signPlanPrice),new BigDecimal(availablePrice));
                yearTotalVo.setIsParking(isParking);
            }else {
                if(type.equals("stage")) {
                    for (YearTotalVo data : yearDataList) {
                        isParking = data.getIsParking();
                        earlyNum = NumberUtils.numAddcalculate(earlyNum,data.getEarlyNum(),isParking);
                        earlyArea = String.valueOf(new BigDecimal(earlyArea).add(new BigDecimal(data.getEarlyArea())));
                        earlyPrice = NumberUtils.priceAddcalculate(earlyPrice,data.getEarlyPrice(),isParking);
                        supplyNum = NumberUtils.numAddcalculate(supplyNum,data.getSupplyNum(),isParking);
                        supplyArea = String.valueOf(new BigDecimal(supplyArea).add(new BigDecimal(data.getSupplyArea())));
                        supplyPrice = NumberUtils.priceAddcalculate(supplyPrice,data.getSupplyPrice(),isParking);
                        availableNum = NumberUtils.numAddcalculate(availableNum,data.getAvailableNum(),isParking);
                        availableArea = String.valueOf(new BigDecimal(availableArea).add(new BigDecimal(data.getAvailableArea())));
                        availablePrice = NumberUtils.priceAddcalculate(availablePrice,data.getAvailablePrice(),isParking);
                        signPlanNum = NumberUtils.numAddcalculate(signPlanNum,data.getSignPlanNum(),isParking);
                        signPlanArea = String.valueOf(new BigDecimal(signPlanArea).add(new BigDecimal(data.getSignPlanArea())));
                        signPlanPrice = NumberUtils.priceAddcalculate(signPlanPrice,data.getSignPlanPrice(),isParking);
                    }
                }else {
                    for (YearTotalVo data : yearDataList) {
                        earlyNum = NumberUtils.numAdd(earlyNum,data.getEarlyNum());
                        earlyArea = String.valueOf(new BigDecimal(earlyArea).add(new BigDecimal(data.getEarlyArea())));
                        earlyPrice = NumberUtils.priceAdd(earlyPrice,data.getEarlyPrice());
                        supplyNum = NumberUtils.numAdd(supplyNum,data.getSupplyNum());
                        supplyArea = String.valueOf(new BigDecimal(supplyArea).add(new BigDecimal(data.getSupplyArea())));
                        supplyPrice = NumberUtils.priceAdd(supplyPrice,data.getSupplyPrice());
                        availableNum = NumberUtils.numAdd(availableNum,data.getAvailableNum());
                        availableArea = String.valueOf(new BigDecimal(availableArea).add(new BigDecimal(data.getAvailableArea())));
                        availablePrice = NumberUtils.priceAdd(availablePrice,data.getAvailablePrice());
                        signPlanNum = NumberUtils.numAdd(signPlanNum,data.getSignPlanNum());
                        signPlanArea = String.valueOf(new BigDecimal(signPlanArea).add(new BigDecimal(data.getSignPlanArea())));
                        signPlanPrice = NumberUtils.priceAdd(signPlanPrice,data.getSignPlanPrice());
                    }
                }
                earlyAvgPrice = NumberUtils.priceDiv(earlyPrice,earlyArea,earlyNum);
                supplyAvgPrice = NumberUtils.priceDiv(supplyPrice,supplyArea,supplyNum);
                availableAvgPrice = NumberUtils.priceDiv(availablePrice,availableArea,availableNum);
                signAvgPlanPrice = NumberUtils.priceDiv(signPlanPrice,signPlanArea,signPlanNum);
                syntheticalPlanRemovalRate = NumberUtils.pricePercentage(signPlanPrice,availablePrice);
            }
            yearTotalVo.setYear(year);
            yearTotalVo.setEarlyNum(earlyNum);
            yearTotalVo.setEarlyArea(earlyArea);
            yearTotalVo.setEarlyAvgPrice(earlyAvgPrice);
            yearTotalVo.setEarlyPrice(earlyPrice);
            yearTotalVo.setSupplyNum(supplyNum);
            yearTotalVo.setSupplyArea(supplyArea);
            yearTotalVo.setSupplyAvgPrice(supplyAvgPrice);
            yearTotalVo.setSupplyPrice(supplyPrice);
            yearTotalVo.setAvailableNum(availableNum);
            yearTotalVo.setAvailableArea(availableArea);
            yearTotalVo.setAvailableAvgPrice(availableAvgPrice);
            yearTotalVo.setAvailablePrice(availablePrice);
            yearTotalVo.setSignPlanNum(signPlanNum);
            yearTotalVo.setSignPlanArea(signPlanArea);
            yearTotalVo.setSignAvgPlanPrice(signAvgPlanPrice);
            yearTotalVo.setSignPlanPrice(signPlanPrice);
            yearTotalVo.setSyntheticalPlanRemovalRate(syntheticalPlanRemovalRate);
            yearTotalVoList.add(yearTotalVo);
        }
        yearTotalVoList.sort(Comparator.comparing(s ->s.getYear()));
        return yearTotalVoList;
    }

    /**
     * 季度签约
     * @param dmAnalyticalVoList 被汇总数据
     * @param type 汇总层级
     * @param isParking 是否车位楼栋
     * @return
     */
    private List<QuarterSignVo> quarterSignVoSummarization(List<DmAnalyticalVo> dmAnalyticalVoList, String type, int isParking) {
        List<QuarterSignVo> quarterSignVoList = new ArrayList<>();
        List<QuarterSignVo> dataList = new ArrayList<>();
        dmAnalyticalVoList.forEach(s -> dataList.addAll(s.getQuarterSignVo()));
        Set<String> quarterList = dataList.stream().map(s -> s.getQuarter()).collect(Collectors.toSet());
        for (String quarter : quarterList){
            QuarterSignVo quarterSignVo = new QuarterSignVo();
            List<QuarterSignVo> quarterDataList = dataList.stream().filter(s -> s.getQuarter().equals(quarter)).collect(Collectors.toList());

            //<季初存货>套数/车位数
            String earlyNum = NumberUtils.stringInitial(2,5);
            //<季初存货>面积
            String earlyArea = NumberUtils.stringInitial(1,4);
            //<季初存货>均价
            String earlyAvgPrice;
            //<季初存货>金额
            String earlyPrice = NumberUtils.stringInitial(3,4);
            //<季度新供>供货套数/车位数
            String supplyNum = NumberUtils.stringInitial(2,5);
            //<季度新供>供货面积
            String supplyArea = NumberUtils.stringInitial(1,4);
            //<季度新供>供货均价
            String supplyAvgPrice;
            //<季度新供>供货金额
            String supplyPrice = NumberUtils.stringInitial(3,4);
            //<季度可售>套数/车位数")
            String availableNum = NumberUtils.stringInitial(2,5);
            //<季度可售>面积
            String availableArea = NumberUtils.stringInitial(1,4);
            //<季度可售>均价
            String availableAvgPrice;
            //<季度可售>金额
            String availablePrice = NumberUtils.stringInitial(3,4);
            //<季度签约计划>套数/车位数
            String signPlanNum = NumberUtils.stringInitial(2,5);
            //<季度签约计划>面积
            String signPlanArea = NumberUtils.stringInitial(1,4);
            //<季度签约计划>均价
            String signAvgPlanPrice;
            //<季度签约计划>金额
            String signPlanPrice = NumberUtils.stringInitial(3,4);
            //<季度综合>计划去化率
            String syntheticalPlanRemovalRate;
            if(type.equals("proProduct")){
                earlyNum = quarterDataList.stream().map(s ->new BigDecimal(s.getEarlyNum())).reduce(BigDecimal.ZERO, BigDecimal::add).toString();
                earlyArea  = quarterDataList.stream().map(s ->new BigDecimal(s.getEarlyArea())).reduce(BigDecimal.ZERO, BigDecimal::add).toString();
                earlyPrice  = quarterDataList.stream().map(s ->new BigDecimal(s.getEarlyPrice())).reduce(BigDecimal.ZERO, BigDecimal::add).toString();
                supplyNum  = quarterDataList.stream().map(s ->new BigDecimal(s.getSupplyNum())).reduce(BigDecimal.ZERO, BigDecimal::add).toString();
                supplyArea  = quarterDataList.stream().map(s ->new BigDecimal(s.getSupplyArea())).reduce(BigDecimal.ZERO, BigDecimal::add).toString();
                supplyPrice  = quarterDataList.stream().map(s ->new BigDecimal(s.getSupplyPrice())).reduce(BigDecimal.ZERO, BigDecimal::add).toString();
                availableNum  = quarterDataList.stream().map(s ->new BigDecimal(s.getAvailableNum())).reduce(BigDecimal.ZERO, BigDecimal::add).toString();
                availableArea  = quarterDataList.stream().map(s ->new BigDecimal(s.getAvailableArea())).reduce(BigDecimal.ZERO, BigDecimal::add).toString();
                availablePrice  = quarterDataList.stream().map(s ->new BigDecimal(s.getAvailablePrice())).reduce(BigDecimal.ZERO, BigDecimal::add).toString();
                signPlanNum  = quarterDataList.stream().map(s ->new BigDecimal(s.getSignPlanNum())).reduce(BigDecimal.ZERO, BigDecimal::add).toString();
                signPlanArea  = quarterDataList.stream().map(s ->new BigDecimal(s.getSignPlanArea())).reduce(BigDecimal.ZERO, BigDecimal::add).toString();
                signPlanPrice  = quarterDataList.stream().map(s ->new BigDecimal(s.getSignPlanPrice())).reduce(BigDecimal.ZERO, BigDecimal::add).toString();

                if(isParking == WhetherEnum.YES.getKey()){
                    earlyAvgPrice = BigDecimalUtils.divBigDecimal(new BigDecimal(earlyPrice),new BigDecimal(earlyNum),4).toString();
                    supplyAvgPrice = BigDecimalUtils.divBigDecimal(new BigDecimal(supplyPrice),new BigDecimal(supplyNum),4).toString();
                    signAvgPlanPrice = BigDecimalUtils.divBigDecimal(new BigDecimal(signPlanPrice),new BigDecimal(signPlanNum),4).toString();
                    availableAvgPrice = BigDecimalUtils.divBigDecimal(new BigDecimal(availablePrice),new BigDecimal(availableNum),4).toString();
                }else {
                    earlyAvgPrice = BigDecimalUtils.divBigDecimal(new BigDecimal(earlyPrice),new BigDecimal(earlyArea),4).toString();
                    supplyAvgPrice = BigDecimalUtils.divBigDecimal(new BigDecimal(supplyPrice),new BigDecimal(supplyArea),4).toString();
                    signAvgPlanPrice = BigDecimalUtils.divBigDecimal(new BigDecimal(signPlanPrice),new BigDecimal(signPlanArea),4).toString();
                    availableAvgPrice = BigDecimalUtils.divBigDecimal(new BigDecimal(availablePrice),new BigDecimal(availableArea),4).toString();
                }
                //<季度综合>计划去化率 = <季度综合>签约计划金额 / <季度综合>可售金额 * 100%
                syntheticalPlanRemovalRate = BigDecimalUtils.calculatedPercentage(new BigDecimal(signPlanPrice),new BigDecimal(availablePrice));
                quarterSignVo.setIsParking(isParking);
            }else {
                if(type.equals("stage")) {
                    for (QuarterSignVo data : quarterDataList) {
                        isParking = data.getIsParking();
                        earlyNum = NumberUtils.numAddcalculate(earlyNum,data.getEarlyNum(),isParking);
                        earlyArea = String.valueOf(new BigDecimal(earlyArea).add(new BigDecimal(data.getEarlyArea())));
                        earlyPrice = NumberUtils.priceAddcalculate(earlyPrice,data.getEarlyPrice(),isParking);
                        supplyNum = NumberUtils.numAddcalculate(supplyNum,data.getSupplyNum(),isParking);
                        supplyArea = String.valueOf(new BigDecimal(supplyArea).add(new BigDecimal(data.getSupplyArea())));
                        supplyPrice = NumberUtils.priceAddcalculate(supplyPrice,data.getSupplyPrice(),isParking);
                        availableNum  = NumberUtils.numAddcalculate(availableNum,data.getAvailableNum(),isParking);
                        availableArea  = String.valueOf(new BigDecimal(availableArea).add(new BigDecimal(data.getAvailableArea())));
                        availablePrice  = NumberUtils.priceAddcalculate(availablePrice,data.getAvailablePrice(),isParking);
                        signPlanNum  = NumberUtils.numAddcalculate(signPlanNum,data.getSignPlanNum(),isParking);
                        signPlanArea  = String.valueOf(new BigDecimal(signPlanArea).add(new BigDecimal(data.getSignPlanArea())));
                        signPlanPrice  = NumberUtils.priceAddcalculate(signPlanPrice,data.getSignPlanPrice(),isParking);
                    }
                }else {
                    for (QuarterSignVo data : quarterDataList) {
                        earlyNum = NumberUtils.numAdd(earlyNum,data.getEarlyNum());
                        earlyArea = String.valueOf(new BigDecimal(earlyArea).add(new BigDecimal(data.getEarlyArea())));
                        earlyPrice = NumberUtils.priceAdd(earlyPrice,data.getEarlyPrice());
                        supplyNum  = NumberUtils.numAdd(supplyNum,data.getSupplyNum());
                        supplyArea  = String.valueOf(new BigDecimal(supplyArea).add(new BigDecimal(data.getSupplyArea())));
                        supplyPrice  = NumberUtils.priceAdd(supplyPrice,data.getSupplyPrice());
                        availableNum  = NumberUtils.numAdd(availableNum,data.getAvailableNum());
                        availableArea  = String.valueOf(new BigDecimal(availableArea).add(new BigDecimal(data.getAvailableArea())));
                        availablePrice  = NumberUtils.priceAdd(availablePrice,data.getAvailablePrice());
                        signPlanNum  = NumberUtils.numAdd(signPlanNum,data.getSignPlanNum());
                        signPlanArea  = String.valueOf(new BigDecimal(signPlanArea).add(new BigDecimal(data.getSignPlanArea())));
                        signPlanPrice  = NumberUtils.priceAdd(signPlanPrice,data.getSignPlanPrice());
                    }
                }
                earlyAvgPrice = NumberUtils.priceDiv(earlyPrice,earlyArea,earlyNum);
                supplyAvgPrice = NumberUtils.priceDiv(supplyPrice,supplyArea,supplyNum);
                signAvgPlanPrice = NumberUtils.priceDiv(signPlanPrice,signPlanArea,signPlanNum);
                availableAvgPrice = NumberUtils.priceDiv(availablePrice,availableArea,availableNum);
                //<季度综合>计划去化率 = <季度综合>签约计划金额 / <季度综合>可售金额 * 100%
                syntheticalPlanRemovalRate = NumberUtils.pricePercentage(signPlanPrice, availablePrice);
            }
            quarterSignVo.setQuarter(quarter);
            quarterSignVo.setEarlyNum(earlyNum);
            quarterSignVo.setEarlyArea(earlyArea);
            quarterSignVo.setEarlyAvgPrice(earlyAvgPrice);
            quarterSignVo.setEarlyPrice(earlyPrice);
            quarterSignVo.setSupplyNum(supplyNum);
            quarterSignVo.setSupplyArea(supplyArea);
            quarterSignVo.setSupplyAvgPrice(supplyAvgPrice);
            quarterSignVo.setSupplyPrice(supplyPrice);
            quarterSignVo.setAvailableNum(availableNum);
            quarterSignVo.setAvailableArea(availableArea);
            quarterSignVo.setAvailableAvgPrice(availableAvgPrice);
            quarterSignVo.setAvailablePrice(availablePrice);
            quarterSignVo.setSignPlanNum(signPlanNum);
            quarterSignVo.setSignPlanArea(signPlanArea);
            quarterSignVo.setSignAvgPlanPrice(signAvgPlanPrice);
            quarterSignVo.setSignPlanPrice(signPlanPrice);
            quarterSignVo.setSyntheticalPlanRemovalRate(syntheticalPlanRemovalRate);
            quarterSignVoList.add(quarterSignVo);

        }
        quarterSignVoList.sort(Comparator.comparing(s ->s.getQuarter()));
        return quarterSignVoList;
    }

    /**
     * 年度签约
     * @param dmAnalyticalVoList 被汇总数据
     * @param type 汇总层级
     * @param isParking 是否车位楼栋
     * @return
     */
    private YearSignVo yearSignVoSummarization(List<DmAnalyticalVo> dmAnalyticalVoList, String type, int isParking) {
        YearSignVo yearSignVo = new YearSignVo();
        List<YearSignVo> dataList = dmAnalyticalVoList.stream().map(s -> s.getYearSignVo()).collect(Collectors.toList());

        //<年初存货>套数/车位数
        String earlyNum = NumberUtils.stringInitial(2,5);
        //<年初存货>面积
        String earlyArea = NumberUtils.stringInitial(1,4);
        //<年初存货>均价
        String earlyAvgPrice;
        //<年初存货>金额
        String earlyPrice = NumberUtils.stringInitial(3,4);
        //<年初存货>签约实际 套数/车位数
        String earlySignActualNum = NumberUtils.stringInitial(2,5);
        //<年初存货>签约实际面积
        String earlySignActualArea = NumberUtils.stringInitial(1,4);
        //<年初存货>签约实际均价
        String earlySignActualAvgPrice;
        //<年初存货>签约实际金额
        String earlySignActualPrice = NumberUtils.stringInitial(3,4);
        //<年度新供>供货计划套数/车位数
        String supplyPlanNum = NumberUtils.stringInitial(2,5);
        //<年度新供>供货计划面积
        String supplyPlanArea = NumberUtils.stringInitial(1,4);
        //<年度新供>供货计划金额
        String supplyPlanPrice = NumberUtils.stringInitial(3,4);
        //<年度新供>供货计划均价
        String supplyPlanAvgPrice;
        //<年度新供>供货实际套数/车位数
        String supplyActualNum = NumberUtils.stringInitial(2,5);
        //<年度新供>供货实际面积
        String supplyActualArea = NumberUtils.stringInitial(1,4);
        //<年度新供>供货实际金额
        String supplyActualPrice = NumberUtils.stringInitial(3,4);
        //<年度新供>供货实际均价
        String supplyActualAvgPrice;
        //<年度新供>签约实际 套数/车位数
        String supplySignActualNum = NumberUtils.stringInitial(2,5);
        //<年度新供>签约实际面积
        String supplySignActualArea = NumberUtils.stringInitial(1,4);
        //<年度新供>签约实际金额
        String supplySignActualPrice = NumberUtils.stringInitial(3,4);
        //<年度新供>签约实际均价
        String supplySignActualAvgPrice;
        //<年度综合>可售 套数/车位数
        String syntheticalAvailableNum = NumberUtils.stringInitial(2,5);
        //<年度综合>可售面积
        String syntheticalAvailableArea = NumberUtils.stringInitial(1,4);
        //<年度综合>可售金额
        String syntheticalAvailablePrice = NumberUtils.stringInitial(3,4);
        //<年度综合>可售均价
        String syntheticalAvailableAvgPrice;
        //<年度综合>签约计划 套数/车位数
        String syntheticalSignPlanNum = NumberUtils.stringInitial(2,5);
        //<年度综合>签约计划面积
        String syntheticalSignPlanArea = NumberUtils.stringInitial(1,4);
        //<年度综合>签约计划金额
        String syntheticalSignPlanPrice = NumberUtils.stringInitial(3,4);
        //<年度综合>签约计划均价
        String syntheticalSignPlanAvgPrice;
        //<年度综合>签约实际 套数/车位数
        String syntheticalSignActualNum = NumberUtils.stringInitial(2,5);
        //<年度综合>签约实际面积
        String syntheticalSignActualArea = NumberUtils.stringInitial(1,4);
        //<年度综合>签约实际金额
        String syntheticalSignActualPrice = NumberUtils.stringInitial(3,4);
        //<年度综合>签约实际均价
        String syntheticalSignActualAvgPrice;
        //<年初存货>实际去化率
        String earlyActualRemovalRate;
        //<年度新供>供货完成率
        String supplyFillRate;
        //<年度新供>实际去化率
        String supplyActualRemovalRate;
        //<年度综合>签约完成率
        String syntheticalSignFillRate;
        //<年度综合>实际去化率
        String syntheticalActualRemovalRate;
        //<年度综合>计划去化率
        String syntheticalPlanRemovalRate;
        if(type.equals("proProduct")){
            earlyNum = dataList.stream().map(s -> new BigDecimal(s.getEarlyNum())).reduce(BigDecimal.ZERO, BigDecimal::add).toString();
            earlyArea = dataList.stream().map(s -> new BigDecimal(s.getEarlyArea())).reduce(BigDecimal.ZERO, BigDecimal::add).toString();
            earlyPrice = dataList.stream().map(s -> new BigDecimal(s.getEarlyPrice())).reduce(BigDecimal.ZERO, BigDecimal::add).toString();
            earlySignActualNum = dataList.stream().map(s -> new BigDecimal(s.getEarlySignActualNum())).reduce(BigDecimal.ZERO, BigDecimal::add).toString();
            earlySignActualArea = dataList.stream().map(s -> new BigDecimal(s.getEarlySignActualArea())).reduce(BigDecimal.ZERO, BigDecimal::add).toString();
            earlySignActualPrice = dataList.stream().map(s -> new BigDecimal(s.getEarlySignActualPrice())).reduce(BigDecimal.ZERO, BigDecimal::add).toString();
            supplyPlanNum = dataList.stream().map(s -> new BigDecimal(s.getSupplyPlanNum())).reduce(BigDecimal.ZERO, BigDecimal::add).toString();
            supplyPlanArea = dataList.stream().map(s -> new BigDecimal(s.getSupplyPlanArea())).reduce(BigDecimal.ZERO, BigDecimal::add).toString();
            supplyPlanPrice = dataList.stream().map(s -> new BigDecimal(s.getSupplyPlanPrice())).reduce(BigDecimal.ZERO, BigDecimal::add).toString();
            supplyActualNum = dataList.stream().map(s -> new BigDecimal(s.getSupplyActualNum())).reduce(BigDecimal.ZERO, BigDecimal::add).toString();
            supplyActualArea = dataList.stream().map(s -> new BigDecimal(s.getSupplyActualArea())).reduce(BigDecimal.ZERO, BigDecimal::add).toString();
            supplyActualPrice = dataList.stream().map(s -> new BigDecimal(s.getSupplyActualPrice())).reduce(BigDecimal.ZERO, BigDecimal::add).toString();
            supplySignActualNum = dataList.stream().map(s -> new BigDecimal(s.getSupplySignActualNum())).reduce(BigDecimal.ZERO, BigDecimal::add).toString();
            supplySignActualArea = dataList.stream().map(s -> new BigDecimal(s.getSupplySignActualArea())).reduce(BigDecimal.ZERO, BigDecimal::add).toString();
            supplySignActualPrice = dataList.stream().map(s -> new BigDecimal(s.getSupplySignActualPrice())).reduce(BigDecimal.ZERO, BigDecimal::add).toString();
            syntheticalAvailableNum = dataList.stream().map(s -> new BigDecimal(s.getSyntheticalAvailableNum())).reduce(BigDecimal.ZERO, BigDecimal::add).toString();
            syntheticalAvailableArea = dataList.stream().map(s -> new BigDecimal(s.getSyntheticalAvailableArea())).reduce(BigDecimal.ZERO, BigDecimal::add).toString();
            syntheticalAvailablePrice = dataList.stream().map(s -> new BigDecimal(s.getSyntheticalAvailablePrice())).reduce(BigDecimal.ZERO, BigDecimal::add).toString();
            syntheticalSignPlanNum = dataList.stream().map(s -> new BigDecimal(s.getSyntheticalSignPlanNum())).reduce(BigDecimal.ZERO, BigDecimal::add).toString();
            syntheticalSignPlanArea = dataList.stream().map(s -> new BigDecimal(s.getSyntheticalSignPlanArea())).reduce(BigDecimal.ZERO, BigDecimal::add).toString();
            syntheticalSignPlanPrice = dataList.stream().map(s -> new BigDecimal(s.getSyntheticalSignPlanPrice())).reduce(BigDecimal.ZERO, BigDecimal::add).toString();
            syntheticalSignActualNum = dataList.stream().map(s -> new BigDecimal(s.getSyntheticalSignActualNum())).reduce(BigDecimal.ZERO, BigDecimal::add).toString();
            syntheticalSignActualArea = dataList.stream().map(s -> new BigDecimal(s.getSyntheticalSignActualArea())).reduce(BigDecimal.ZERO, BigDecimal::add).toString();
            syntheticalSignActualPrice = dataList.stream().map(s -> new BigDecimal(s.getSyntheticalSignActualPrice())).reduce(BigDecimal.ZERO, BigDecimal::add).toString();

            if(isParking == WhetherEnum.YES.getKey()){
                earlyAvgPrice = BigDecimalUtils.divBigDecimal(new BigDecimal(earlyPrice),new BigDecimal(earlyNum),4).toString();
                earlySignActualAvgPrice = BigDecimalUtils.divBigDecimal(new BigDecimal(earlySignActualPrice),new BigDecimal(earlySignActualNum),4).toString();
                supplyPlanAvgPrice = BigDecimalUtils.divBigDecimal(new BigDecimal(supplyPlanPrice),new BigDecimal(supplyPlanNum),4).toString();
                supplyActualAvgPrice = BigDecimalUtils.divBigDecimal(new BigDecimal(supplyActualPrice),new BigDecimal(supplyActualNum),4).toString();
                supplySignActualAvgPrice = BigDecimalUtils.divBigDecimal(new BigDecimal(supplySignActualPrice),new BigDecimal(supplySignActualNum),4).toString();
                syntheticalAvailableAvgPrice = BigDecimalUtils.divBigDecimal(new BigDecimal(syntheticalAvailablePrice),new BigDecimal(syntheticalAvailableNum),4).toString();
                syntheticalSignPlanAvgPrice = BigDecimalUtils.divBigDecimal(new BigDecimal(syntheticalSignPlanPrice),new BigDecimal(syntheticalSignPlanNum),4).toString();
                syntheticalSignActualAvgPrice = BigDecimalUtils.divBigDecimal(new BigDecimal(syntheticalSignActualPrice),new BigDecimal(syntheticalSignActualNum),4).toString();
            }else {
                earlyAvgPrice = BigDecimalUtils.divBigDecimal(new BigDecimal(earlyPrice),new BigDecimal(earlyArea),4).toString();
                earlySignActualAvgPrice = BigDecimalUtils.divBigDecimal(new BigDecimal(earlySignActualPrice),new BigDecimal(earlySignActualArea),4).toString();
                supplyPlanAvgPrice = BigDecimalUtils.divBigDecimal(new BigDecimal(supplyPlanPrice),new BigDecimal(supplyPlanArea),4).toString();
                supplyActualAvgPrice = BigDecimalUtils.divBigDecimal(new BigDecimal(supplyActualPrice),new BigDecimal(supplyActualArea),4).toString();
                supplySignActualAvgPrice = BigDecimalUtils.divBigDecimal(new BigDecimal(supplySignActualPrice),new BigDecimal(supplySignActualArea),4).toString();
                syntheticalAvailableAvgPrice = BigDecimalUtils.divBigDecimal(new BigDecimal(syntheticalAvailablePrice),new BigDecimal(syntheticalAvailableArea),4).toString();
                syntheticalSignPlanAvgPrice = BigDecimalUtils.divBigDecimal(new BigDecimal(syntheticalSignPlanPrice),new BigDecimal(syntheticalSignPlanArea),4).toString();
                syntheticalSignActualAvgPrice = BigDecimalUtils.divBigDecimal(new BigDecimal(syntheticalSignActualPrice),new BigDecimal(syntheticalSignActualArea),4).toString();
            }
            earlyActualRemovalRate = BigDecimalUtils.calculatedPercentage(new BigDecimal(earlySignActualPrice),new BigDecimal(earlyPrice));
            supplyFillRate = BigDecimalUtils.calculatedPercentage(new BigDecimal(supplyActualPrice),new BigDecimal(supplyPlanPrice));
            supplyActualRemovalRate = BigDecimalUtils.calculatedPercentage(new BigDecimal(supplySignActualPrice),new BigDecimal(supplyActualPrice));
            syntheticalSignFillRate = BigDecimalUtils.calculatedPercentage(new BigDecimal(syntheticalSignActualPrice),new BigDecimal(syntheticalSignPlanPrice));
            syntheticalActualRemovalRate = BigDecimalUtils.calculatedPercentage(new BigDecimal(syntheticalSignActualPrice),new BigDecimal(syntheticalAvailablePrice));
            syntheticalPlanRemovalRate = BigDecimalUtils.calculatedPercentage(new BigDecimal(syntheticalSignPlanPrice),new BigDecimal(syntheticalAvailablePrice));
            yearSignVo.setIsParking(isParking);
        }else {
            if(type.equals("stage")){
                for (YearSignVo data : dataList){
                    isParking = data.getIsParking();
                    earlyNum = NumberUtils.numAddcalculate(earlyNum,data.getEarlyNum(),isParking);
                    earlyArea = String.valueOf(new BigDecimal(earlyArea).add(new BigDecimal(data.getEarlyArea())));
                    earlyPrice = NumberUtils.priceAddcalculate(earlyPrice,data.getEarlyPrice(),isParking);
                    earlySignActualNum = NumberUtils.numAddcalculate(earlySignActualNum,data.getEarlySignActualNum(),isParking);
                    earlySignActualArea = String.valueOf(new BigDecimal(earlySignActualArea).add(new BigDecimal(data.getEarlySignActualArea())));
                    earlySignActualPrice = NumberUtils.priceAddcalculate(earlySignActualPrice,data.getEarlySignActualPrice(),isParking);
                    supplyPlanNum = NumberUtils.numAddcalculate(supplyPlanNum,data.getSupplyPlanNum(),isParking);
                    supplyPlanArea = String.valueOf(new BigDecimal(supplyPlanArea).add(new BigDecimal(data.getSupplyPlanArea())));
                    supplyPlanPrice = NumberUtils.priceAddcalculate(supplyPlanPrice,data.getSupplyPlanPrice(),isParking);
                    supplyActualNum = NumberUtils.numAddcalculate(supplyActualNum,data.getSupplyActualNum(),isParking);
                    supplyActualArea = String.valueOf(new BigDecimal(supplyActualArea).add(new BigDecimal(data.getSupplyActualArea())));
                    supplyActualPrice = NumberUtils.priceAddcalculate(supplyActualPrice,data.getSupplyActualPrice(),isParking);
                    supplySignActualNum = NumberUtils.numAddcalculate(supplySignActualNum,data.getSupplySignActualNum(),isParking);
                    supplySignActualArea = String.valueOf(new BigDecimal(supplySignActualArea).add(new BigDecimal(data.getSupplySignActualArea())));
                    supplySignActualPrice = NumberUtils.priceAddcalculate(supplySignActualPrice,data.getSupplySignActualPrice(),isParking);
                    syntheticalAvailableNum = NumberUtils.numAddcalculate(syntheticalAvailableNum,data.getSyntheticalAvailableNum(),isParking);
                    syntheticalAvailableArea = String.valueOf(new BigDecimal(syntheticalAvailableArea).add(new BigDecimal(data.getSyntheticalAvailableArea())));
                    syntheticalAvailablePrice = NumberUtils.priceAddcalculate(syntheticalAvailablePrice,data.getSyntheticalAvailablePrice(),isParking);
                    syntheticalSignPlanNum = NumberUtils.numAddcalculate(syntheticalSignPlanNum,data.getSyntheticalSignPlanNum(),isParking);
                    syntheticalSignPlanArea = String.valueOf(new BigDecimal(syntheticalSignPlanArea).add(new BigDecimal(data.getSyntheticalSignPlanArea())));
                    syntheticalSignPlanPrice = NumberUtils.priceAddcalculate(syntheticalSignPlanPrice,data.getSyntheticalSignPlanPrice(),isParking);
                    syntheticalSignActualNum = NumberUtils.numAddcalculate(syntheticalSignActualNum,data.getSyntheticalSignActualNum(),isParking);
                    syntheticalSignActualArea = String.valueOf(new BigDecimal(syntheticalSignActualArea).add(new BigDecimal(data.getSyntheticalSignActualArea())));
                    syntheticalSignActualPrice = NumberUtils.priceAddcalculate(syntheticalSignActualPrice,data.getSyntheticalSignActualPrice(),isParking);
                }
            }else {
                for (YearSignVo data : dataList){
                    earlyNum = NumberUtils.numAdd(earlyNum,data.getEarlyNum());
                    earlyArea = String.valueOf(new BigDecimal(earlyArea).add(new BigDecimal(data.getEarlyArea())));
                    earlyPrice = NumberUtils.priceAdd(earlyPrice,data.getEarlyPrice());
                    earlySignActualNum = NumberUtils.numAdd(earlySignActualNum,data.getEarlySignActualNum());
                    earlySignActualArea = String.valueOf(new BigDecimal(earlySignActualArea).add(new BigDecimal(data.getEarlySignActualArea())));
                    earlySignActualPrice = NumberUtils.priceAdd(earlySignActualPrice,data.getEarlySignActualPrice());
                    supplyPlanNum = NumberUtils.numAdd(supplyPlanNum,data.getSupplyPlanNum());
                    supplyPlanArea = String.valueOf(new BigDecimal(supplyPlanArea).add(new BigDecimal(data.getSupplyPlanArea())));
                    supplyPlanPrice = NumberUtils.priceAdd(supplyPlanPrice,data.getSupplyPlanPrice());
                    supplyActualNum = NumberUtils.numAdd(supplyActualNum,data.getSupplyActualNum());
                    supplyActualArea = String.valueOf(new BigDecimal(supplyActualArea).add(new BigDecimal(data.getSupplyActualArea())));
                    supplyActualPrice = NumberUtils.priceAdd(supplyActualPrice,data.getSupplyActualPrice());
                    supplySignActualNum = NumberUtils.numAdd(supplySignActualNum,data.getSupplySignActualNum());
                    supplySignActualArea = String.valueOf(new BigDecimal(supplySignActualArea).add(new BigDecimal(data.getSupplySignActualArea())));
                    supplySignActualPrice = NumberUtils.priceAdd(supplySignActualPrice,data.getSupplySignActualPrice());
                    syntheticalAvailableNum = NumberUtils.numAdd(syntheticalAvailableNum,data.getSyntheticalAvailableNum());
                    syntheticalAvailableArea = String.valueOf(new BigDecimal(syntheticalAvailableArea).add(new BigDecimal(data.getSyntheticalAvailableArea())));
                    syntheticalAvailablePrice = NumberUtils.priceAdd(syntheticalAvailablePrice,data.getSyntheticalAvailablePrice());
                    syntheticalSignPlanNum = NumberUtils.numAdd(syntheticalSignPlanNum,data.getSyntheticalSignPlanNum());
                    syntheticalSignPlanArea = String.valueOf(new BigDecimal(syntheticalSignPlanArea).add(new BigDecimal(data.getSyntheticalSignPlanArea())));
                    syntheticalSignPlanPrice = NumberUtils.priceAdd(syntheticalSignPlanPrice,data.getSyntheticalSignPlanPrice());
                    syntheticalSignActualNum = NumberUtils.numAdd(syntheticalSignActualNum,data.getSyntheticalSignActualNum());
                    syntheticalSignActualArea = String.valueOf(new BigDecimal(syntheticalSignActualArea).add(new BigDecimal(data.getSyntheticalSignActualArea())));
                    syntheticalSignActualPrice = NumberUtils.priceAdd(syntheticalSignActualPrice,data.getSyntheticalSignActualPrice());
                }
            }
            earlyAvgPrice = NumberUtils.priceDiv(earlyPrice,earlyArea,earlyNum);
            earlySignActualAvgPrice = NumberUtils.priceDiv(earlySignActualPrice,earlySignActualArea,earlySignActualNum);
            supplyPlanAvgPrice = NumberUtils.priceDiv(supplyPlanPrice,supplyPlanArea,supplyPlanNum);
            supplyActualAvgPrice = NumberUtils.priceDiv(supplyActualPrice,supplyActualArea,supplyActualNum);
            supplySignActualAvgPrice = NumberUtils.priceDiv(supplySignActualPrice,supplySignActualArea,supplySignActualNum);
            syntheticalAvailableAvgPrice = NumberUtils.priceDiv(syntheticalAvailablePrice,syntheticalAvailableArea,syntheticalAvailableNum);
            syntheticalSignPlanAvgPrice = NumberUtils.priceDiv(syntheticalSignPlanPrice,syntheticalSignPlanArea,syntheticalSignPlanNum);
            syntheticalSignActualAvgPrice = NumberUtils.priceDiv(syntheticalSignActualPrice,syntheticalSignActualArea,syntheticalSignActualNum);
            earlyActualRemovalRate = NumberUtils.pricePercentage(earlySignActualPrice,earlyPrice);
            supplyFillRate = NumberUtils.pricePercentage(supplyActualPrice,supplyPlanPrice);
            supplyActualRemovalRate = NumberUtils.pricePercentage(supplySignActualPrice,supplyActualPrice);
            syntheticalSignFillRate = NumberUtils.pricePercentage(syntheticalSignActualPrice,syntheticalSignPlanPrice);
            syntheticalActualRemovalRate = NumberUtils.pricePercentage(syntheticalSignActualPrice,syntheticalAvailablePrice);
            syntheticalPlanRemovalRate = NumberUtils.pricePercentage(syntheticalSignPlanPrice,syntheticalAvailablePrice);
        }

        yearSignVo.setYear(dataList.get(0).getYear());
        yearSignVo.setEarlyNum(String.valueOf(earlyNum));
        yearSignVo.setEarlyArea(String.valueOf(earlyArea));
        yearSignVo.setEarlyAvgPrice(earlyAvgPrice);
        yearSignVo.setEarlyPrice(String.valueOf(earlyPrice));
        yearSignVo.setEarlySignActualNum(String.valueOf(earlySignActualNum));
        yearSignVo.setEarlySignActualArea(String.valueOf(earlySignActualArea));
        yearSignVo.setEarlySignActualAvgPrice(String.valueOf(earlySignActualAvgPrice));
        yearSignVo.setEarlySignActualPrice(String.valueOf(earlySignActualPrice));
        yearSignVo.setEarlyActualRemovalRate(String.valueOf(earlyActualRemovalRate));
        yearSignVo.setSupplyPlanNum(String.valueOf(supplyPlanNum));
        yearSignVo.setSupplyPlanArea(String.valueOf(supplyPlanArea));
        yearSignVo.setSupplyPlanAvgPrice(String.valueOf(supplyPlanAvgPrice));
        yearSignVo.setSupplyPlanPrice(String.valueOf(supplyPlanPrice));
        yearSignVo.setSupplyActualNum(String.valueOf(supplyActualNum));
        yearSignVo.setSupplyActualArea(String.valueOf(supplyActualArea));
        yearSignVo.setSupplyActualAvgPrice(String.valueOf(supplyActualAvgPrice));
        yearSignVo.setSupplyActualPrice(String.valueOf(supplyActualPrice));
        yearSignVo.setSupplyFillRate(String.valueOf(supplyFillRate));
        yearSignVo.setSupplySignActualNum(String.valueOf(supplySignActualNum));
        yearSignVo.setSupplySignActualArea(String.valueOf(supplySignActualArea));
        yearSignVo.setSupplySignActualAvgPrice(String.valueOf(supplySignActualAvgPrice));
        yearSignVo.setSupplySignActualPrice(String.valueOf(supplySignActualPrice));
        yearSignVo.setSupplyActualRemovalRate(String.valueOf(supplyActualRemovalRate));
        yearSignVo.setSyntheticalAvailableNum(String.valueOf(syntheticalAvailableNum));
        yearSignVo.setSyntheticalAvailableArea(String.valueOf(syntheticalAvailableArea));
        yearSignVo.setSyntheticalAvailableAvgPrice(String.valueOf(syntheticalAvailableAvgPrice));
        yearSignVo.setSyntheticalAvailablePrice(String.valueOf(syntheticalAvailablePrice));
        yearSignVo.setSyntheticalSignPlanNum(String.valueOf(syntheticalSignPlanNum));
        yearSignVo.setSyntheticalSignPlanArea(String.valueOf(syntheticalSignPlanArea));
        yearSignVo.setSyntheticalSignPlanAvgPrice(String.valueOf(syntheticalSignPlanAvgPrice));
        yearSignVo.setSyntheticalSignPlanPrice(String.valueOf(syntheticalSignPlanPrice));
        yearSignVo.setSyntheticalSignActualNum(String.valueOf(syntheticalSignActualNum));
        yearSignVo.setSyntheticalSignActualArea(String.valueOf(syntheticalSignActualArea));
        yearSignVo.setSyntheticalSignActualAvgPrice(String.valueOf(syntheticalSignActualAvgPrice));
        yearSignVo.setSyntheticalSignActualPrice(String.valueOf(syntheticalSignActualPrice));
        yearSignVo.setSyntheticalSignFillRate(String.valueOf(syntheticalSignFillRate));
        yearSignVo.setSyntheticalActualRemovalRate(String.valueOf(syntheticalActualRemovalRate));
        yearSignVo.setSyntheticalPlanRemovalRate(String.valueOf(syntheticalPlanRemovalRate));
        return yearSignVo;

    }

    /**
     * 月度签约向上汇总
     * @param dmAnalyticalVoList 被汇总数据
     * @param type 汇总层级
     * @param isParking 是否车位楼栋
     * @return
     */
    private List<MonthSignVo> monthSignVoSummarization(List<DmAnalyticalVo> dmAnalyticalVoList, String type, int isParking) {
        List<MonthSignVo> monthSignVoList = new ArrayList<>();
        List<MonthSignVo> dataList = new ArrayList<>();
        dmAnalyticalVoList.forEach(s -> dataList.addAll(s.getMonthSignVo()));
        Set<String> yearMonthList = dataList.stream().map(s -> s.getYearMonth()).collect(Collectors.toSet());
        for (String yearMonth : yearMonthList){
            MonthSignVo monthSignVo = new MonthSignVo();

            List<MonthSignVo> monthDataList = dataList.stream().filter(s -> s.getYearMonth().equals(yearMonth)).collect(Collectors.toList());

            //<月初存货>套数/车位数
            String earlyNum = NumberUtils.stringInitial(2,5);
            // <月初存货>面积
            String earlyArea = NumberUtils.stringInitial(1,4);
            //<月初存货>均价
            String avgEarlyPrice;
            //<月初存货>金额
            String earlyPrice = NumberUtils.stringInitial(3,4);
            //<月初存货>签约计划 套数/车位数
            String earlySignPlanNum = NumberUtils.stringInitial(2,5);
            //<月初存货>签约计划面积
            String earlySignPlanArea = NumberUtils.stringInitial(1,4);
            // <月初存货>签约计划均价
            String earlyAvgSignPlanPrice;
            //<月初存货>签约计划金额
            String earlySignPlanPrice = NumberUtils.stringInitial(3,4);
            //<月初存货>签约实际 套数/车位数
            String earlySignActualNum = NumberUtils.stringInitial(2,5);
            //<月初存货>签约实际面积
            String earlySignActualArea = NumberUtils.stringInitial(1,4);
            //<月初存货>签约实际均价
            String earlyAvgSignActualPrice;
            //<月初存货>签约实际金额
            String earlySignActualPrice = NumberUtils.stringInitial(3,4);
            //月度新供>供货计划套数/车位数
            String supplyPlanNum = NumberUtils.stringInitial(2,5);
            //<月度新供>供货计划面积
            String supplyPlanArea = NumberUtils.stringInitial(1,4);
            //<月度新供>供货计划均价
            String supplyAvgPlanPrice;
            //<月度新供>供货计划金额
            String supplyPlanPrice = NumberUtils.stringInitial(3,4);
            //<月度新供>供货实际套数/车位数
            String supplyActualNum = NumberUtils.stringInitial(2,5);
            //<月度新供>供货实际面积
            String supplyActualArea = NumberUtils.stringInitial(1,4);
            //<月度新供>供货实际均价
            String supplyAvgActualPrice;
            //<月度新供>供货实际金额
            String supplyActualPrice = NumberUtils.stringInitial(3,4);
            //<月度新供>签约计划 套数/车位数
            String supplySignPlanNum = NumberUtils.stringInitial(2,5);
            //<月度新供>签约计划面积
            String supplySignPlanArea = NumberUtils.stringInitial(1,4);
            //<月度新供>签约计划均价
            String supplyAvgSignPlanPrice;
            //<月度新供>签约计划金额
            String supplySignPlanPrice = NumberUtils.stringInitial(3,4);
            //<月度新供>签约实际 套数/车位数
            String supplySignActualNum = NumberUtils.stringInitial(2,5);
            //<月度新供>签约实际面积
            String supplySignActualArea = NumberUtils.stringInitial(1,4);
            //<月度新供>签约实际均价
            String supplyAvgSignActualPrice;
            //<月度新供>签约实际金额
            String supplySignActualPrice = NumberUtils.stringInitial(3,4);
            //<月度综合>可售 套数/车位数
            String syntheticalAvailableNum = NumberUtils.stringInitial(2,5);
            //<月度综合>可售面积
            String syntheticalAvailableArea = NumberUtils.stringInitial(1,4);
            //<月度综合>可售金额
            String syntheticalAvailablePrice = NumberUtils.stringInitial(3,4);
            //月度综合>可售均价
            String syntheticalAvailableAvgPrice;
            //<月度综合>签约计划 套数/车位数
            String syntheticalSignPlanNum = NumberUtils.stringInitial(2,5);
            //<月度综合>签约计划面积
            String syntheticalSignPlanArea = NumberUtils.stringInitial(1,4);
            //<月度综合>签约计划金额
            String syntheticalSignPlanPrice = NumberUtils.stringInitial(3,4);
            //<月度综合>签约计划均价
            String syntheticalAvgSignPlanPrice;
            //<月度综合>签约实际 套数/车位数
            String syntheticalSignActualNum = NumberUtils.stringInitial(2,5);
            //<月度综合>签约实际面积
            String syntheticalSignActualArea = NumberUtils.stringInitial(1,4);
            //<月度综合>签约实际金额
            String syntheticalSignActualPrice = NumberUtils.stringInitial(3,4);
            //<月度综合>签约实际均价
            String syntheticalAvgSignActualPrice;
            //<月初存货>签约完成率
            String earlySignFillRate;
            //<月初存货>实际去化率
            String earlyActualRemovalRate;
            //<月初存货>计划去化率
            String earlyPlanRemovalRate;
            //<月度新供>供货完成率
            String supplyFillRate;
            //<月度新供>签约完成率
            String supplySignFillRate;
            //<月度新供>实际去化率
            String supplyActualRemovalRate;
            //<月度新供>计划去化率
            String supplyPlanRemovalRate;
            //<月度综合>签约完成率
            String syntheticalSignFillRate;
            //<月度综合>实际去化率
            String syntheticalActualRemovalRate;
            //<月度综合>计划去化率
            String syntheticalPlanRemovalRate;

            if(type.equals("proProduct")){
                earlyNum = monthDataList.stream().map(s -> new BigDecimal(s.getEarlyNum())).reduce(BigDecimal.ZERO, BigDecimal::add).toString();
                earlyArea = monthDataList.stream().map(s -> new BigDecimal(s.getEarlyArea())).reduce(BigDecimal.ZERO, BigDecimal::add).toString();
                earlyPrice = monthDataList.stream().map(s -> new BigDecimal(s.getEarlyPrice())).reduce(BigDecimal.ZERO, BigDecimal::add).toString();
                earlySignPlanNum = monthDataList.stream().map(s -> new BigDecimal(s.getEarlySignPlanNum())).reduce(BigDecimal.ZERO, BigDecimal::add).toString();
                earlySignPlanArea = monthDataList.stream().map(s -> new BigDecimal(s.getEarlySignPlanArea())).reduce(BigDecimal.ZERO, BigDecimal::add).toString();
                earlySignPlanPrice = monthDataList.stream().map(s -> new BigDecimal(s.getEarlySignPlanPrice())).reduce(BigDecimal.ZERO, BigDecimal::add).toString();
                earlySignActualNum = monthDataList.stream().map(s -> new BigDecimal(s.getEarlySignActualNum())).reduce(BigDecimal.ZERO, BigDecimal::add).toString();
                earlySignActualArea = monthDataList.stream().map(s -> new BigDecimal(s.getEarlySignActualArea())).reduce(BigDecimal.ZERO, BigDecimal::add).toString();
                earlySignActualPrice = monthDataList.stream().map(s -> new BigDecimal(s.getEarlySignActualPrice())).reduce(BigDecimal.ZERO, BigDecimal::add).toString();
                supplyPlanNum = monthDataList.stream().map(s -> new BigDecimal(s.getSupplyPlanNum())).reduce(BigDecimal.ZERO, BigDecimal::add).toString();
                supplyPlanArea = monthDataList.stream().map(s -> new BigDecimal(s.getSupplyPlanArea())).reduce(BigDecimal.ZERO, BigDecimal::add).toString();
                supplyPlanPrice = monthDataList.stream().map(s -> new BigDecimal(s.getSupplyPlanPrice())).reduce(BigDecimal.ZERO, BigDecimal::add).toString();
                supplyActualNum = monthDataList.stream().map(s -> new BigDecimal(s.getSupplyActualNum())).reduce(BigDecimal.ZERO, BigDecimal::add).toString();
                supplyActualArea = monthDataList.stream().map(s -> new BigDecimal(s.getSupplyActualArea())).reduce(BigDecimal.ZERO, BigDecimal::add).toString();
                supplyActualPrice = monthDataList.stream().map(s -> new BigDecimal(s.getSupplyActualPrice())).reduce(BigDecimal.ZERO, BigDecimal::add).toString();
                supplySignPlanNum = monthDataList.stream().map(s -> new BigDecimal(s.getSupplySignPlanNum())).reduce(BigDecimal.ZERO, BigDecimal::add).toString();
                supplySignPlanArea = monthDataList.stream().map(s -> new BigDecimal(s.getSupplySignPlanArea())).reduce(BigDecimal.ZERO, BigDecimal::add).toString();
                supplySignPlanPrice = monthDataList.stream().map(s -> new BigDecimal(s.getSupplySignPlanPrice())).reduce(BigDecimal.ZERO, BigDecimal::add).toString();
                supplySignActualNum = monthDataList.stream().map(s -> new BigDecimal(s.getSupplySignActualNum())).reduce(BigDecimal.ZERO, BigDecimal::add).toString();
                supplySignActualArea = monthDataList.stream().map(s -> new BigDecimal(s.getSupplySignActualArea())).reduce(BigDecimal.ZERO, BigDecimal::add).toString();
                supplySignActualPrice = monthDataList.stream().map(s -> new BigDecimal(s.getSupplySignActualPrice())).reduce(BigDecimal.ZERO, BigDecimal::add).toString();
                syntheticalAvailableNum = monthDataList.stream().map(s -> new BigDecimal(s.getSyntheticalAvailableNum())).reduce(BigDecimal.ZERO, BigDecimal::add).toString();
                syntheticalAvailableArea = monthDataList.stream().map(s -> new BigDecimal(s.getSyntheticalAvailableArea())).reduce(BigDecimal.ZERO, BigDecimal::add).toString();
                syntheticalAvailablePrice = monthDataList.stream().map(s -> new BigDecimal(s.getSyntheticalAvailablePrice())).reduce(BigDecimal.ZERO, BigDecimal::add).toString();
                syntheticalSignPlanNum = monthDataList.stream().map(s -> new BigDecimal(s.getSyntheticalSignPlanNum())).reduce(BigDecimal.ZERO, BigDecimal::add).toString();
                syntheticalSignPlanArea = monthDataList.stream().map(s -> new BigDecimal(s.getSyntheticalSignPlanArea())).reduce(BigDecimal.ZERO, BigDecimal::add).toString();
                syntheticalSignPlanPrice = monthDataList.stream().map(s -> new BigDecimal(s.getSyntheticalSignPlanPrice())).reduce(BigDecimal.ZERO, BigDecimal::add).toString();
                syntheticalSignActualNum = monthDataList.stream().map(s -> new BigDecimal(s.getSyntheticalSignActualNum())).reduce(BigDecimal.ZERO, BigDecimal::add).toString();
                syntheticalSignActualArea = monthDataList.stream().map(s -> new BigDecimal(s.getSyntheticalSignActualArea())).reduce(BigDecimal.ZERO, BigDecimal::add).toString();
                syntheticalSignActualPrice = monthDataList.stream().map(s -> new BigDecimal(s.getSyntheticalSignActualPrice())).reduce(BigDecimal.ZERO, BigDecimal::add).toString();

                if(isParking == WhetherEnum.YES.getKey()){
                    avgEarlyPrice = BigDecimalUtils.divBigDecimal(new BigDecimal(earlyPrice),new BigDecimal(earlyNum),4).toString();
                    earlyAvgSignPlanPrice = BigDecimalUtils.divBigDecimal(new BigDecimal(earlySignPlanPrice),new BigDecimal(earlySignPlanNum),4).toString();
                    earlyAvgSignActualPrice = BigDecimalUtils.divBigDecimal(new BigDecimal(earlySignActualPrice),new BigDecimal(earlySignActualNum),4).toString();
                    supplyAvgPlanPrice = BigDecimalUtils.divBigDecimal(new BigDecimal(supplyPlanPrice),new BigDecimal(supplyPlanNum),4).toString();
                    supplyAvgActualPrice = BigDecimalUtils.divBigDecimal(new BigDecimal(supplyActualPrice),new BigDecimal(supplyActualNum),4).toString();
                    supplyAvgSignPlanPrice = BigDecimalUtils.divBigDecimal(new BigDecimal(supplySignPlanPrice),new BigDecimal(supplySignPlanNum),4).toString();
                    supplyAvgSignActualPrice = BigDecimalUtils.divBigDecimal(new BigDecimal(supplySignActualPrice),new BigDecimal(supplySignActualNum),4).toString();
                    syntheticalAvailableAvgPrice = BigDecimalUtils.divBigDecimal(new BigDecimal(syntheticalAvailablePrice),new BigDecimal(syntheticalAvailableNum),4).toString();
                    syntheticalAvgSignPlanPrice = BigDecimalUtils.divBigDecimal(new BigDecimal(syntheticalSignPlanPrice),new BigDecimal(syntheticalSignPlanNum),4).toString();
                    syntheticalAvgSignActualPrice = BigDecimalUtils.divBigDecimal(new BigDecimal(syntheticalSignActualPrice),new BigDecimal(syntheticalSignActualNum),4).toString();
                }else {
                    avgEarlyPrice = BigDecimalUtils.divBigDecimal(new BigDecimal(earlyPrice),new BigDecimal(earlyArea),4).toString();
                    earlyAvgSignPlanPrice = BigDecimalUtils.divBigDecimal(new BigDecimal(earlySignPlanPrice),new BigDecimal(earlySignPlanArea),4).toString();
                    earlyAvgSignActualPrice = BigDecimalUtils.divBigDecimal(new BigDecimal(earlySignActualPrice),new BigDecimal(earlySignActualArea),4).toString();
                    supplyAvgPlanPrice = BigDecimalUtils.divBigDecimal(new BigDecimal(supplyPlanPrice),new BigDecimal(supplyPlanArea),4).toString();
                    supplyAvgActualPrice = BigDecimalUtils.divBigDecimal(new BigDecimal(supplyActualPrice),new BigDecimal(supplyActualArea),4).toString();
                    supplyAvgSignPlanPrice = BigDecimalUtils.divBigDecimal(new BigDecimal(supplySignPlanPrice),new BigDecimal(supplySignPlanArea),4).toString();
                    supplyAvgSignActualPrice = BigDecimalUtils.divBigDecimal(new BigDecimal(supplySignActualPrice),new BigDecimal(supplySignActualArea),4).toString();
                    syntheticalAvailableAvgPrice = BigDecimalUtils.divBigDecimal(new BigDecimal(syntheticalAvailablePrice),new BigDecimal(syntheticalAvailableArea),4).toString();
                    syntheticalAvgSignPlanPrice = BigDecimalUtils.divBigDecimal(new BigDecimal(syntheticalSignPlanPrice),new BigDecimal(syntheticalSignPlanArea),4).toString();
                    syntheticalAvgSignActualPrice = BigDecimalUtils.divBigDecimal(new BigDecimal(syntheticalSignActualPrice),new BigDecimal(syntheticalSignActualArea),4).toString();
                }
                earlySignFillRate = BigDecimalUtils.calculatedPercentage(new BigDecimal(earlySignActualPrice), new BigDecimal(earlySignPlanPrice));
                earlyActualRemovalRate = BigDecimalUtils.calculatedPercentage(new BigDecimal(earlySignActualPrice),new BigDecimal(earlyPrice));
                earlyPlanRemovalRate = BigDecimalUtils.calculatedPercentage(new BigDecimal(earlySignPlanPrice),new BigDecimal(earlyPrice));
                supplyFillRate = BigDecimalUtils.calculatedPercentage(new BigDecimal(supplyActualPrice),new BigDecimal(supplyPlanPrice));
                supplySignFillRate = BigDecimalUtils.calculatedPercentage(new BigDecimal(supplySignActualPrice),new BigDecimal(supplySignPlanPrice));
                supplyActualRemovalRate = BigDecimalUtils.calculatedPercentage(new BigDecimal(supplySignActualPrice),new BigDecimal(supplyActualPrice));
                supplyPlanRemovalRate = BigDecimalUtils.calculatedPercentage(new BigDecimal(supplySignPlanPrice),new BigDecimal(supplyPlanPrice));
                syntheticalSignFillRate = BigDecimalUtils.calculatedPercentage(new BigDecimal(syntheticalSignActualPrice),new BigDecimal(syntheticalSignPlanPrice));
                syntheticalActualRemovalRate = BigDecimalUtils.calculatedPercentage(new BigDecimal(syntheticalSignActualPrice),new BigDecimal(syntheticalAvailablePrice));
                syntheticalPlanRemovalRate = BigDecimalUtils.calculatedPercentage(new BigDecimal(syntheticalSignPlanPrice),new BigDecimal(syntheticalAvailablePrice));
                monthSignVo.setIsParking(isParking);
            }else {
                if(type.equals("stage")){
                    for (MonthSignVo data : monthDataList){
                        isParking = data.getIsParking();
                        earlyNum = NumberUtils.numAddcalculate(earlyNum,data.getEarlyNum(),isParking);
                        earlyArea = String.valueOf(new BigDecimal(earlyArea).add(new BigDecimal(data.getEarlyArea())));
                        earlyPrice = NumberUtils.priceAddcalculate(earlyPrice,data.getEarlyPrice(),isParking);
                        earlySignPlanNum = NumberUtils.numAddcalculate(earlySignPlanNum,data.getEarlySignPlanNum(),isParking);
                        earlySignPlanArea = String.valueOf(new BigDecimal(earlySignPlanArea).add(new BigDecimal(data.getEarlySignPlanArea())));
                        earlySignPlanPrice = NumberUtils.priceAddcalculate(earlySignPlanPrice,data.getEarlySignPlanPrice(),isParking);
                        earlySignActualNum = NumberUtils.numAddcalculate(earlySignActualNum,data.getEarlySignActualNum(),isParking);
                        earlySignActualArea = String.valueOf(new BigDecimal(earlySignActualArea).add(new BigDecimal(data.getEarlySignActualArea())));
                        earlySignActualPrice = NumberUtils.priceAddcalculate(earlySignActualPrice,data.getEarlySignActualPrice(),isParking);
                        supplyPlanNum = NumberUtils.numAddcalculate(supplyPlanNum,data.getSupplyPlanNum(),isParking);
                        supplyPlanArea = String.valueOf(new BigDecimal(supplyPlanArea).add(new BigDecimal(data.getSupplyPlanArea())));
                        supplyPlanPrice = NumberUtils.priceAddcalculate(supplyPlanPrice,data.getSupplyPlanPrice(),isParking);
                        supplyActualNum = NumberUtils.numAddcalculate(supplyActualNum,data.getSupplyActualNum(),isParking);
                        supplyActualArea = String.valueOf(new BigDecimal(supplyActualArea).add(new BigDecimal(data.getSupplyActualArea())));
                        supplyActualPrice = NumberUtils.priceAddcalculate(supplyActualPrice,data.getSupplyActualPrice(),isParking);
                        supplySignPlanNum = NumberUtils.numAddcalculate(supplySignPlanNum,data.getSupplySignPlanNum(),isParking);
                        supplySignPlanArea = String.valueOf(new BigDecimal(supplySignPlanArea).add(new BigDecimal(data.getSupplySignPlanArea())));
                        supplySignPlanPrice = NumberUtils.priceAddcalculate(supplySignPlanPrice,data.getSupplySignPlanPrice(),isParking);
                        supplySignActualNum = NumberUtils.numAddcalculate(supplySignActualNum,data.getSupplySignActualNum(),isParking);
                        supplySignActualArea = String.valueOf(new BigDecimal(supplySignActualArea).add(new BigDecimal(data.getSupplySignActualArea())));
                        supplySignActualPrice = NumberUtils.priceAddcalculate(supplySignActualPrice,data.getSupplySignActualPrice(),isParking);
                        syntheticalAvailableNum = NumberUtils.numAddcalculate(syntheticalAvailableNum,data.getSyntheticalAvailableNum(),isParking);
                        syntheticalAvailableArea = String.valueOf(new BigDecimal(syntheticalAvailableArea).add(new BigDecimal(data.getSyntheticalAvailableArea())));
                        syntheticalAvailablePrice = NumberUtils.priceAddcalculate(syntheticalAvailablePrice,data.getSyntheticalAvailablePrice(),isParking);
                        syntheticalSignPlanNum = NumberUtils.numAddcalculate(syntheticalSignPlanNum,data.getSyntheticalSignPlanNum(),isParking);
                        syntheticalSignPlanArea = String.valueOf(new BigDecimal(syntheticalSignPlanArea).add(new BigDecimal(data.getSyntheticalSignPlanArea())));
                        syntheticalSignPlanPrice = NumberUtils.priceAddcalculate(syntheticalSignPlanPrice,data.getSyntheticalSignPlanPrice(),isParking);
                        syntheticalSignActualNum = NumberUtils.numAddcalculate(syntheticalSignActualNum,data.getSyntheticalSignActualNum(),isParking);
                        syntheticalSignActualArea = String.valueOf(new BigDecimal(syntheticalSignActualArea).add(new BigDecimal(data.getSyntheticalSignActualArea())));
                        syntheticalSignActualPrice = NumberUtils.priceAddcalculate(syntheticalSignActualPrice,data.getSyntheticalSignActualPrice(),isParking);
                    }
                }else {
                    for (MonthSignVo data : monthDataList){
                        earlyNum = NumberUtils.numAdd(earlyNum,data.getEarlyNum());
                        earlyArea = String.valueOf(new BigDecimal(earlyArea).add(new BigDecimal(data.getEarlyArea())));
                        earlyPrice = NumberUtils.priceAdd(earlyPrice,data.getEarlyPrice());
                        earlySignPlanNum = NumberUtils.numAdd(earlySignPlanNum,data.getEarlySignPlanNum());
                        earlySignPlanArea = String.valueOf(new BigDecimal(earlySignPlanArea).add(new BigDecimal(data.getEarlySignPlanArea())));
                        earlySignPlanPrice = NumberUtils.priceAdd(earlySignPlanPrice,data.getEarlySignPlanPrice());
                        earlySignActualNum = NumberUtils.numAdd(earlySignActualNum,data.getEarlySignActualNum());
                        earlySignActualArea = String.valueOf(new BigDecimal(earlySignActualArea).add(new BigDecimal(data.getEarlySignActualArea())));
                        earlySignActualPrice = NumberUtils.priceAdd(earlySignActualPrice,data.getEarlySignActualPrice());
                        supplyPlanNum = NumberUtils.numAdd(supplyPlanNum,data.getSupplyPlanNum());
                        supplyPlanArea = String.valueOf(new BigDecimal(supplyPlanArea).add(new BigDecimal(data.getSupplyPlanArea())));
                        supplyPlanPrice = NumberUtils.priceAdd(supplyPlanPrice,data.getSupplyPlanPrice());
                        supplyActualNum = NumberUtils.numAdd(supplyActualNum,data.getSupplyActualNum());
                        supplyActualArea = String.valueOf(new BigDecimal(supplyActualArea).add(new BigDecimal(data.getSupplyActualArea())));
                        supplyActualPrice = NumberUtils.priceAdd(supplyActualPrice,data.getSupplyActualPrice());
                        supplySignPlanNum = NumberUtils.numAdd(supplySignPlanNum,data.getSupplySignPlanNum());
                        supplySignPlanArea = String.valueOf(new BigDecimal(supplySignPlanArea).add(new BigDecimal(data.getSupplySignPlanArea())));
                        supplySignPlanPrice = NumberUtils.priceAdd(supplySignPlanPrice,data.getSupplySignPlanPrice());
                        supplySignActualNum = NumberUtils.numAdd(supplySignActualNum,data.getSupplySignActualNum());
                        supplySignActualArea = String.valueOf(new BigDecimal(supplySignActualArea).add(new BigDecimal(data.getSupplySignActualArea())));
                        supplySignActualPrice = NumberUtils.priceAdd(supplySignActualPrice,data.getSupplySignActualPrice());
                        syntheticalAvailableNum = NumberUtils.numAdd(syntheticalAvailableNum,data.getSyntheticalAvailableNum());
                        syntheticalAvailableArea = String.valueOf(new BigDecimal(syntheticalAvailableArea).add(new BigDecimal(data.getSyntheticalAvailableArea())));
                        syntheticalAvailablePrice = NumberUtils.priceAdd(syntheticalAvailablePrice,data.getSyntheticalAvailablePrice());
                        syntheticalSignPlanNum = NumberUtils.numAdd(syntheticalSignPlanNum,data.getSyntheticalSignPlanNum());
                        syntheticalSignPlanArea = String.valueOf(new BigDecimal(syntheticalSignPlanArea).add(new BigDecimal(data.getSyntheticalSignPlanArea())));
                        syntheticalSignPlanPrice = NumberUtils.priceAdd(syntheticalSignPlanPrice,data.getSyntheticalSignPlanPrice());
                        syntheticalSignActualNum = NumberUtils.numAdd(syntheticalSignActualNum,data.getSyntheticalSignActualNum());
                        syntheticalSignActualArea = String.valueOf(new BigDecimal(syntheticalSignActualArea).add(new BigDecimal(data.getSyntheticalSignActualArea())));
                        syntheticalSignActualPrice = NumberUtils.priceAdd(syntheticalSignActualPrice,data.getSyntheticalSignActualPrice());
                    }
                }
                avgEarlyPrice = NumberUtils.priceDiv(earlyPrice,earlyArea,earlyNum);
                earlyAvgSignPlanPrice = NumberUtils.priceDiv(earlySignPlanPrice,earlySignPlanArea,earlySignPlanNum);
                earlyAvgSignActualPrice = NumberUtils.priceDiv(earlySignActualPrice,earlySignActualArea,earlySignActualNum);
                supplyAvgPlanPrice = NumberUtils.priceDiv(supplyPlanPrice,supplyPlanArea,supplyPlanNum);
                supplyAvgActualPrice = NumberUtils.priceDiv(supplyActualPrice,supplyActualArea,supplyActualNum);
                supplyAvgSignPlanPrice = NumberUtils.priceDiv(supplySignPlanPrice,supplySignPlanArea,supplySignPlanNum);
                supplyAvgSignActualPrice = NumberUtils.priceDiv(supplySignActualPrice,supplySignActualArea,supplySignActualNum);
                syntheticalAvailableAvgPrice = NumberUtils.priceDiv(syntheticalAvailablePrice,syntheticalAvailableArea,syntheticalAvailableNum);
                syntheticalAvgSignPlanPrice = NumberUtils.priceDiv(syntheticalSignPlanPrice,syntheticalSignPlanArea,syntheticalSignPlanNum);
                syntheticalAvgSignActualPrice = NumberUtils.priceDiv(syntheticalSignActualPrice,syntheticalSignActualArea,syntheticalSignActualNum);
                earlySignFillRate = NumberUtils.pricePercentage(earlySignActualPrice,earlySignPlanPrice);
                earlyActualRemovalRate = NumberUtils.pricePercentage(earlySignActualPrice,earlyPrice);
                earlyPlanRemovalRate = NumberUtils.pricePercentage(earlySignPlanPrice,earlyPrice);
                supplyFillRate = NumberUtils.pricePercentage(supplyActualPrice,supplyPlanPrice);
                supplySignFillRate = NumberUtils.pricePercentage(supplySignActualPrice,supplySignPlanPrice);
                supplyActualRemovalRate = NumberUtils.pricePercentage(supplySignActualPrice,supplyActualPrice);
                supplyPlanRemovalRate = NumberUtils.pricePercentage(supplySignPlanPrice,supplyPlanPrice);
                syntheticalSignFillRate = NumberUtils.pricePercentage(syntheticalSignActualPrice,syntheticalSignPlanPrice);
                syntheticalActualRemovalRate = NumberUtils.pricePercentage(syntheticalSignActualPrice,syntheticalAvailablePrice);
                syntheticalPlanRemovalRate = NumberUtils.pricePercentage(syntheticalSignPlanPrice,syntheticalAvailablePrice);
            }
            monthSignVo.setYearMonth(yearMonth);
            monthSignVo.setEarlyNum(String.valueOf(earlyNum));
            monthSignVo.setEarlyArea(String.valueOf(earlyArea));
            monthSignVo.setAvgEarlyPrice(String.valueOf(avgEarlyPrice));
            monthSignVo.setEarlyPrice(String.valueOf(earlyPrice));
            monthSignVo.setEarlySignPlanNum(String.valueOf(earlySignPlanNum));
            monthSignVo.setEarlySignPlanArea(String.valueOf(earlySignPlanArea));
            monthSignVo.setEarlyAvgSignPlanPrice(String.valueOf(earlyAvgSignPlanPrice));
            monthSignVo.setEarlySignPlanPrice(String.valueOf(earlySignPlanPrice));
            monthSignVo.setEarlySignActualNum(String.valueOf(earlySignActualNum));
            monthSignVo.setEarlySignActualArea(String.valueOf(earlySignActualArea));
            monthSignVo.setEarlyAvgSignActualPrice(String.valueOf(earlyAvgSignActualPrice));
            monthSignVo.setEarlySignActualPrice(String.valueOf(earlySignActualPrice));
            monthSignVo.setEarlySignFillRate(earlySignFillRate);
            monthSignVo.setEarlyActualRemovalRate(earlyActualRemovalRate);
            monthSignVo.setEarlyPlanRemovalRate(earlyPlanRemovalRate);
            monthSignVo.setSupplyPlanNum(String.valueOf(supplyPlanNum));
            monthSignVo.setSupplyPlanArea(String.valueOf(supplyPlanArea));
            monthSignVo.setSupplyAvgPlanPrice(String.valueOf(supplyAvgPlanPrice));
            monthSignVo.setSupplyPlanPrice(String.valueOf(supplyPlanPrice));
            monthSignVo.setSupplyActualNum(String.valueOf(supplyActualNum));
            monthSignVo.setSupplyActualArea(String.valueOf(supplyActualArea));
            monthSignVo.setSupplyAvgActualPrice(String.valueOf(supplyAvgActualPrice));
            monthSignVo.setSupplyActualPrice(String.valueOf(supplyActualPrice));
            monthSignVo.setSupplyFillRate(supplyFillRate);
            monthSignVo.setSupplySignPlanNum(String.valueOf(supplySignPlanNum));
            monthSignVo.setSupplySignPlanArea(String.valueOf(supplySignPlanArea));
            monthSignVo.setSupplyAvgSignPlanPrice(String.valueOf(supplyAvgSignPlanPrice));
            monthSignVo.setSupplySignPlanPrice(String.valueOf(supplySignPlanPrice));
            monthSignVo.setSupplySignActualNum(String.valueOf(supplySignActualNum));
            monthSignVo.setSupplySignActualArea(String.valueOf(supplySignActualArea));
            monthSignVo.setSupplyAvgSignActualPrice(String.valueOf(supplyAvgSignActualPrice));
            monthSignVo.setSupplySignActualPrice(String.valueOf(supplySignActualPrice));
            monthSignVo.setSupplySignFillRate(supplySignFillRate);
            monthSignVo.setSupplyActualRemovalRate(supplyActualRemovalRate);
            monthSignVo.setSupplyPlanRemovalRate(supplyPlanRemovalRate);
            monthSignVo.setSyntheticalAvailableNum(String.valueOf(syntheticalAvailableNum));
            monthSignVo.setSyntheticalAvailableArea(String.valueOf(syntheticalAvailableArea));
            monthSignVo.setSyntheticalAvailableAvgPrice(String.valueOf(syntheticalAvailableAvgPrice));
            monthSignVo.setSyntheticalAvailablePrice(String.valueOf(syntheticalAvailablePrice));
            monthSignVo.setSyntheticalSignPlanNum(String.valueOf(syntheticalSignPlanNum));
            monthSignVo.setSyntheticalSignPlanArea(String.valueOf(syntheticalSignPlanArea));
            monthSignVo.setSyntheticalAvgSignPlanPrice(String.valueOf(syntheticalAvgSignPlanPrice));
            monthSignVo.setSyntheticalSignPlanPrice(String.valueOf(syntheticalSignPlanPrice));
            monthSignVo.setSyntheticalSignActualNum(String.valueOf(syntheticalSignActualNum));
            monthSignVo.setSyntheticalSignActualArea(String.valueOf(syntheticalSignActualArea));
            monthSignVo.setSyntheticalAvgSignActualPrice(String.valueOf(syntheticalAvgSignActualPrice));
            monthSignVo.setSyntheticalSignActualPrice(String.valueOf(syntheticalSignActualPrice));
            monthSignVo.setSyntheticalSignFillRate(syntheticalSignFillRate);
            monthSignVo.setSyntheticalActualRemovalRate(syntheticalActualRemovalRate);
            monthSignVo.setSyntheticalPlanRemovalRate(syntheticalPlanRemovalRate);
            monthSignVoList.add(monthSignVo);
        }
        monthSignVoList.sort(Comparator.comparing(s ->s.getYearMonth()));
        return monthSignVoList;
    }

    /**
     * 当年以前签约向上汇总
     * @param dmAnalyticalVoList 被汇总数据
     * @param type 汇总层级
     * @param isParking 是否车位楼栋
     * @return
     */
    private PastYearVo pastYearVoSummarization(List<DmAnalyticalVo> dmAnalyticalVoList, String type,int isParking) {
        PastYearVo pastYearVo = new PastYearVo();
        List<PastYearVo> dataList = dmAnalyticalVoList.stream().map(s -> s.getPastYearVo()).collect(Collectors.toList());

        //总可售货值-套数
        String availableNum = NumberUtils.stringInitial(2,5);
        //总可售货值-面积
        String availableArea = NumberUtils.stringInitial(1,4);
        //总可售货值-均价
        String availableAvgPrice;
        //总可售货值-金额
        String availablePrice = NumberUtils.stringInitial(3,4);
        //签约实际-套数
        String signActualNum = NumberUtils.stringInitial(2,5);
        //签约实际-面积
        String signActualArea = NumberUtils.stringInitial(1,4);
        //签约实际-均价
        String signAvgActualPrice;
        //签约实际-金额
        String signActualPrice = NumberUtils.stringInitial(3,4);
        //签约计划-套数
        String signPlanNum = NumberUtils.stringInitial(2,5);
        //签约计划-面积
        String signPlanArea = NumberUtils.stringInitial(1,4);
        //签约计划-均价
        String signAvgPlanPrice;
        //签约计划-金额
        String signPlanPrice = NumberUtils.stringInitial(3,4);
        // 签约完成率
        String signFillRate;
        // 实际去化率
        String actualRemovalRate;
        // 计划去化率
        String planRemovalRate;
        if(type.equals("proProduct")){
            availableNum = dataList.stream().map(s -> new BigDecimal(s.getAvailableNum())).reduce(BigDecimal.ZERO, BigDecimal::add).toString();
            availableArea = dataList.stream().map(s -> new BigDecimal(s.getAvailableArea())).reduce(BigDecimal.ZERO, BigDecimal::add).toString();
            availablePrice = dataList.stream().map(s -> new BigDecimal(s.getAvailablePrice())).reduce(BigDecimal.ZERO, BigDecimal::add).toString();
            signActualNum = dataList.stream().map(s -> new BigDecimal(s.getSignActualNum())).reduce(BigDecimal.ZERO, BigDecimal::add).toString();
            signActualArea = dataList.stream().map(s -> new BigDecimal(s.getSignActualArea())).reduce(BigDecimal.ZERO, BigDecimal::add).toString();
            signActualPrice = dataList.stream().map(s -> new BigDecimal(s.getSignActualPrice())).reduce(BigDecimal.ZERO, BigDecimal::add).toString();
            signPlanNum = dataList.stream().map(s -> new BigDecimal(s.getSignPlanNum())).reduce(BigDecimal.ZERO, BigDecimal::add).toString();
            signPlanArea = dataList.stream().map(s -> new BigDecimal(s.getSignPlanArea())).reduce(BigDecimal.ZERO, BigDecimal::add).toString();
            signPlanPrice = dataList.stream().map(s -> new BigDecimal(s.getSignPlanPrice())).reduce(BigDecimal.ZERO, BigDecimal::add).toString();

            if(isParking == WhetherEnum.YES.getKey()){
                availableAvgPrice = BigDecimalUtils.divBigDecimal(new BigDecimal(availablePrice),new BigDecimal(availableNum),4).toString();
                signAvgActualPrice = BigDecimalUtils.divBigDecimal(new BigDecimal(signActualPrice),new BigDecimal(signActualNum),4).toString();
                signAvgPlanPrice = BigDecimalUtils.divBigDecimal(new BigDecimal(signPlanPrice),new BigDecimal(signPlanNum),4).toString();
            }else {
                availableAvgPrice = BigDecimalUtils.divBigDecimal(new BigDecimal(availablePrice),new BigDecimal(availableArea),4).toString();
                signAvgActualPrice = BigDecimalUtils.divBigDecimal(new BigDecimal(signActualPrice),new BigDecimal(signActualArea),4).toString();
                signAvgPlanPrice = BigDecimalUtils.divBigDecimal(new BigDecimal(signPlanPrice),new BigDecimal(signPlanArea),4).toString();
            }
            signFillRate = BigDecimalUtils.calculatedPercentage(new BigDecimal(signActualPrice),new BigDecimal(signPlanPrice));
            actualRemovalRate = BigDecimalUtils.calculatedPercentage(new BigDecimal(signActualPrice),new BigDecimal(availablePrice));
            planRemovalRate = BigDecimalUtils.calculatedPercentage(new BigDecimal(signPlanPrice),new BigDecimal(availablePrice));
            pastYearVo.setIsParking(isParking);
        }else {
            if(type.equals("stage")){
                for (PastYearVo data : dataList){
                    isParking = data.getIsParking();
                    availableNum = NumberUtils.numAddcalculate(availableNum,data.getAvailableNum(),isParking);
                    availableArea = String.valueOf(new BigDecimal(availableArea).add(new BigDecimal(data.getAvailableArea())));
                    availablePrice = NumberUtils.priceAddcalculate(availablePrice,data.getAvailablePrice(),isParking);
                    signActualNum = NumberUtils.numAddcalculate(signActualNum,data.getSignActualNum(),isParking);
                    signActualArea = String.valueOf(new BigDecimal(signActualArea).add(new BigDecimal(data.getSignActualArea())));
                    signActualPrice = NumberUtils.priceAddcalculate(signActualPrice,data.getSignActualPrice(),isParking);
                    signPlanNum = NumberUtils.numAddcalculate(signPlanNum,data.getSignPlanNum(),isParking);
                    signPlanArea = String.valueOf(new BigDecimal(signPlanArea).add(new BigDecimal(data.getSignPlanArea())));
                    signPlanPrice = NumberUtils.priceAddcalculate(signPlanPrice,data.getSignPlanPrice(),isParking);
                }
            }else {
                for (PastYearVo data : dataList){
                    availableNum = NumberUtils.numAdd(availableNum,data.getAvailableNum());
                    availableArea = String.valueOf(new BigDecimal(availableArea).add(new BigDecimal(data.getAvailableArea())));
                    availablePrice = NumberUtils.priceAdd(availablePrice,data.getAvailablePrice());
                    signActualNum = NumberUtils.numAdd(signActualNum,data.getSignActualNum());
                    signActualArea = String.valueOf(new BigDecimal(signActualArea).add(new BigDecimal(data.getSignActualArea())));
                    signActualPrice = NumberUtils.priceAdd(signActualPrice,data.getSignActualPrice());
                    signPlanNum = NumberUtils.numAdd(signPlanNum,data.getSignPlanNum());
                    signPlanArea = String.valueOf(new BigDecimal(signPlanArea).add(new BigDecimal(data.getSignPlanArea())));
                    signPlanPrice = NumberUtils.priceAdd(signPlanPrice,data.getSignPlanPrice());
                }
            }
            availableAvgPrice = NumberUtils.priceDiv(availablePrice,availableArea,availableNum);
            signAvgActualPrice = NumberUtils.priceDiv(signActualPrice,signActualArea,signActualNum);
            signAvgPlanPrice = NumberUtils.priceDiv(signPlanPrice,signPlanArea,signPlanNum);
            signFillRate = NumberUtils.pricePercentage(signActualPrice,signPlanPrice);
            actualRemovalRate = NumberUtils.pricePercentage(signActualPrice,availablePrice);
            planRemovalRate = NumberUtils.pricePercentage(signPlanPrice,availablePrice);
        }
        pastYearVo.setAvailableNum(availableNum);
        pastYearVo.setAvailableArea(availableArea);
        pastYearVo.setAvailableAvgPrice(availableAvgPrice);
        pastYearVo.setAvailablePrice(availablePrice);
        pastYearVo.setSignActualNum(signActualNum);
        pastYearVo.setSignActualArea(signActualArea);
        pastYearVo.setSignAvgActualPrice(signAvgActualPrice);
        pastYearVo.setSignActualPrice(signActualPrice);
        pastYearVo.setSignPlanNum(signPlanNum);
        pastYearVo.setSignPlanArea(signPlanArea);
        pastYearVo.setSignAvgPlanPrice(signAvgPlanPrice);
        pastYearVo.setSignPlanPrice(signPlanPrice);
        pastYearVo.setSignFillRate(signFillRate);
        pastYearVo.setActualRemovalRate(actualRemovalRate);
        pastYearVo.setPlanRemovalRate(planRemovalRate);

        return pastYearVo;
    }


    /**
     * 计算业态组合层级的签约数据
     * @param YearSignList
     * @param MonthSignList
     * @param year
     * @return
     */
    private DmAnalyticalVo getDmAnalyticalVo(List<DmDmPlanSignYear> YearSignList, List<DmDmPlanSignMonth> MonthSignList, String year) {
        DmAnalyticalVo vo = new DmAnalyticalVo();

        int isParking = MonthSignList.get(0).getIsParking();
        //计算当年以前签约
        PastYearVo pastYearVo = getPastYearVo(YearSignList, year, isParking);
        //月度签约
        List<MonthSignVo> monthSignVoList = getMonthSignVo(MonthSignList, year, isParking);
        //年度签约
        YearSignVo yearSignVo = getYearSignVo(YearSignList, year ,isParking);
        //季度签约
        List<QuarterSignVo> quarterSignVo = getQuarterSignVo(MonthSignList, year,isParking);
        //年度合计签约
        List<YearTotalVo> yearTotalVo = getYearTotalVo(YearSignList, year,isParking);

        DmDmPlanSignMonth monthSign = MonthSignList.get(0);
        vo.setId(monthSign.getVersionId()+monthSign.getProProductCode()+monthSign.getCombinationCode());
        vo.setPid(monthSign.getVersionId()+monthSign.getProProductCode());
        vo.setIsParking(monthSign.getIsParking());
        vo.setType("combination");
        vo.setCityCompanyId(monthSign.getCityCompanyId());
        vo.setCityCompanyName(monthSign.getCityCompanyName());
        vo.setBusinessDivisionId(monthSign.getBusinessDivisionId());
        vo.setBusinessDivisionName(monthSign.getBusinessDivisionName());
        vo.setProjectId(monthSign.getProjectId());
        vo.setProjectName(monthSign.getProjectName());
        vo.setProjectCode(monthSign.getProjectCode());
        vo.setIsFirstOpen(monthSign.getIsFirstOpen());
        vo.setIsContinueOpen(monthSign.getIsContinueOpen());
        vo.setStageName(monthSign.getStageName());
        vo.setStageCode(monthSign.getStageCode());
        vo.setEquityRatio(monthSign.getEquityRatio());
        vo.setOpmarketing(monthSign.getOpmarketing());
        vo.setIsAndTable(monthSign.getIsAndTable());
        vo.setExistingHouses(monthSign.getExistingHouses());
        vo.setGroupName(monthSign.getGroupName());
        vo.setProProductName(monthSign.getProProductType());
        vo.setProProductCode(monthSign.getProProductCode());
        vo.setProductName(monthSign.getProductName());
        vo.setProductCode(monthSign.getProductCode());
        vo.setBusinessTypeName(monthSign.getBusinessTypeName());
        vo.setFreeTypeName(monthSign.getFreeTypeName());
        vo.setProTypeName(monthSign.getProTypeName());
        vo.setPastYearVo(pastYearVo);
        vo.setMonthSignVo(monthSignVoList);
        vo.setYearSignVo(yearSignVo);
        vo.setQuarterSignVo(quarterSignVo);
        vo.setYearTotalVo(yearTotalVo);
        return vo;
    }

    /**
     * 年度合计签约
     * @param yearSignList
     * @param year
     * @param isParking
     * @return
     */
    private List<YearTotalVo> getYearTotalVo(List<DmDmPlanSignYear> yearSignList, String year, int isParking) {
        List<YearTotalVo> yearTotalVoList = new ArrayList<>();

        List<DmDmPlanSignYear> yearTotalSignList = yearSignList.stream().filter(s -> Integer.valueOf(s.getYear()) > Integer.valueOf(year)).collect(Collectors.toList());
        Set<String> yearList = yearTotalSignList.stream().map(s -> s.getYear()).collect(Collectors.toSet());
        for (String y : yearList){
            YearTotalVo yearTotalVo = new YearTotalVo();
            yearTotalVo.setYear(y);
            DmDmPlanSignYear yearSign = yearTotalSignList.stream().filter(s -> s.getYear().equals(y)).collect(Collectors.toList()).get(0);

            //<年初存货>套数/车位数
            BigDecimal earlyNum;
            //<年初存货>面积
            BigDecimal earlyArea;
            //<年初存货>均价
            BigDecimal earlyAvgPrice;
            //<年初存货>金额
            BigDecimal earlyPrice;
            //<年度新供>供货计划套数/车位数
            BigDecimal supplyNum;
            //<年度新供>供货计划面积
            BigDecimal supplyArea;
            //<年度新供>供货计划均价
            BigDecimal supplyAvgPrice;
            //<年度新供>供货计划金额
            BigDecimal supplyPrice;
            //<年度可售>套数/车位数
            BigDecimal availableNum;
            //<年度可售>面积
            BigDecimal availableArea;
            //<年度可售>均价
            BigDecimal availableAvgPrice;
            //<年度可售>金额
            BigDecimal availablePrice;
            //<年度签约计划>套数/车位数
            BigDecimal signPlanNum;
            //<年度签约计划>面积
            BigDecimal signPlanArea;
            //<年度签约计划>均价
            BigDecimal signAvgPlanPrice;
            //<年度签约计划>金额
            BigDecimal signPlanPrice;
            if(isParking == WhetherEnum.YES.getKey()){
                earlyNum = yearSign.getEarlyNumC();
                earlyArea = yearSign.getEarlyAreaC();
                earlyAvgPrice = yearSign.getEarlyAvgPriceC();
                earlyPrice = yearSign.getEarlyPriceC();
                supplyNum = yearSign.getSupplyNumC();
                supplyArea = yearSign.getSupplyAreaC();
                supplyAvgPrice = yearSign.getSupplyAvgPriceC();
                supplyPrice = yearSign.getSupplyPriceC();
                availableNum = yearSign.getSyntheticalAvailableNumC();
                availableArea = yearSign.getSyntheticalAvailableAreaC();
                availableAvgPrice = yearSign.getSyntheticalAvailableAvgPriceC();
                availablePrice = yearSign.getSyntheticalAvailablePriceC();
                signPlanNum = yearSign.getSyntheticalSignPlanNumC();
                signPlanArea = yearSign.getSyntheticalSignPlanAreaC();
                signAvgPlanPrice = yearSign.getSyntheticalSignPlanAvgPriceC();
                signPlanPrice = yearSign.getSyntheticalSignPlanPriceC();
            }else {
                earlyNum = yearSign.getEarlyNum();
                earlyArea = yearSign.getEarlyArea();
                earlyAvgPrice = yearSign.getEarlyAvgPrice();
                earlyPrice = yearSign.getEarlyPrice();
                supplyNum = yearSign.getSupplyNum();
                supplyArea = yearSign.getSupplyArea();
                supplyAvgPrice = yearSign.getSupplyAvgPrice();
                supplyPrice = yearSign.getSupplyPrice();
                availableNum = yearSign.getSyntheticalAvailableNum();
                availableArea = yearSign.getSyntheticalAvailableArea();
                availableAvgPrice = yearSign.getSyntheticalAvailableAvgPrice();
                availablePrice = yearSign.getSyntheticalAvailablePrice();
                signPlanNum = yearSign.getSyntheticalSignPlanNum();
                signPlanArea = yearSign.getSyntheticalSignPlanArea();
                signAvgPlanPrice = yearSign.getSyntheticalSignPlanAvgPrice();
                signPlanPrice = yearSign.getSyntheticalSignPlanPrice();
            }
            //<年度综合>计划去化率 = <年度综合>签约计划金额 / <年度综合>可售
            String syntheticalPlanRemovalRate = BigDecimalUtils.calculatedPercentageA(signPlanPrice,availablePrice);

            yearTotalVo.setIsParking(isParking);
            yearTotalVo.setEarlyNum(String.valueOf(earlyNum));
            yearTotalVo.setEarlyArea(String.valueOf(earlyArea));
            yearTotalVo.setEarlyAvgPrice(String.valueOf(earlyAvgPrice));
            yearTotalVo.setEarlyPrice(String.valueOf(earlyPrice));
            yearTotalVo.setSupplyNum(String.valueOf(supplyNum));
            yearTotalVo.setSupplyArea(String.valueOf(supplyArea));
            yearTotalVo.setSupplyAvgPrice(String.valueOf(supplyAvgPrice));
            yearTotalVo.setSupplyPrice(String.valueOf(supplyPrice));
            yearTotalVo.setAvailableNum(String.valueOf(availableNum));
            yearTotalVo.setAvailableArea(String.valueOf(availableArea));
            yearTotalVo.setAvailableAvgPrice(String.valueOf(availableAvgPrice));
            yearTotalVo.setAvailablePrice(String.valueOf(availablePrice));
            yearTotalVo.setSignPlanNum(String.valueOf(signPlanNum));
            yearTotalVo.setSignPlanArea(String.valueOf(signPlanArea));
            yearTotalVo.setSignAvgPlanPrice(String.valueOf(signAvgPlanPrice));
            yearTotalVo.setSignPlanPrice(String.valueOf(signPlanPrice));
            yearTotalVo.setSyntheticalPlanRemovalRate(syntheticalPlanRemovalRate);
            yearTotalVoList.add(yearTotalVo);
        }
        yearTotalVoList.sort(Comparator.comparing(s ->s.getYear()));

        return yearTotalVoList;
    }

    /**
     * 季度签约
     * @param monthSignList
     * @param year
     * @param isParking
     * @return
     */
    private List<QuarterSignVo> getQuarterSignVo(List<DmDmPlanSignMonth> monthSignList, String year, int isParking) {
        List<QuarterSignVo> quarterSignVo = new ArrayList<>();

        List<DmDmPlanSignMonth> monthSigns = monthSignList.stream().filter(s -> s.getSignPlanTime().getMonthValue() < Integer.valueOf(year)).collect(Collectors.toList());
        int quarter = 1;
        for (int i = 1; i <12 ; i+=3) {
            QuarterSignVo vo = new QuarterSignVo();
            vo.setQuarter(String.valueOf(quarter++));
            int month = i;
            //季度数据
            List<DmDmPlanSignMonth> quarterSignList = monthSigns.stream().filter(s -> s.getSignPlanTime().getMonthValue() >= month && s.getSignPlanTime().getMonthValue() < month+3 ).collect(Collectors.toList());
            //季初数据
            List<DmDmPlanSignMonth> quarterEarlyList = monthSigns.stream().filter(s -> s.getSignPlanTime().getMonthValue() >= month && s.getSignPlanTime().getMonthValue() < month+3 ).collect(Collectors.toList());

            //<季初存货>套数/车位数
            BigDecimal earlyNum;
            //<季初存货>面积
            BigDecimal earlyArea;
            //<季初存货>均价
            BigDecimal earlyAvgPrice;
            //<季初存货>金额
            BigDecimal earlyPrice;
            //<季度新供>供货套数/车位数
            BigDecimal supplyNum;
            //<季度新供>供货面积
            BigDecimal supplyArea;
            //<季度新供>供货均价
            BigDecimal supplyAvgPrice;
            //<季度新供>供货金额
            BigDecimal supplyPrice;
            //<季度可售>套数/车位数")
            BigDecimal availableNum;
            //<季度可售>面积
            BigDecimal availableArea;
            //<季度可售>均价
            BigDecimal availableAvgPrice;
            //<季度可售>金额
            BigDecimal availablePrice;
            //<季度签约计划>套数/车位数
            BigDecimal signPlanNum;
            //<季度签约计划>面积
            BigDecimal signPlanArea;
            //<季度签约计划>均价
            BigDecimal signAvgPlanPrice;
            //<季度签约计划>金额
            BigDecimal signPlanPrice;
            if(isParking==WhetherEnum.YES.getKey()){
                if(CollectionUtils.isEmpty(quarterEarlyList)){
                    earlyNum = BigDecimal.ZERO;
                    earlyArea = BigDecimal.ZERO;
                    earlyAvgPrice = BigDecimal.ZERO;
                    earlyPrice = BigDecimal.ZERO;
                }else {
                    DmDmPlanSignMonth quarterEarly = quarterEarlyList.get(0);
                    earlyNum = quarterEarly.getEarlyRoomCountC();
                    earlyArea = quarterEarly.getEarlyRoomAreaC();
                    earlyAvgPrice = quarterEarly.getEarlyAvgPriceC();
                    earlyPrice = quarterEarly.getEarlySumPriceC();
                }
                supplyNum = quarterSignList.stream().map(s -> s.getSupplyRoomCountC()).reduce(BigDecimal.ZERO, BigDecimal::add);
                supplyArea = quarterSignList.stream().map(s -> s.getSupplyRoomAreaC()).reduce(BigDecimal.ZERO, BigDecimal::add);
                supplyPrice = quarterSignList.stream().map(s -> s.getSupplySumPriceC()).reduce(BigDecimal.ZERO, BigDecimal::add);

                signPlanNum = quarterSignList.stream().map(s -> s.getEarlySignRoomCountPlanC().add(s.getSupplySignRoomCountPlanC())).reduce(BigDecimal.ZERO, BigDecimal::add);
                signPlanArea = quarterSignList.stream().map(s -> s.getEarlySignRoomAreaPlanC().add(s.getSupplySignRoomAreaPlanC())).reduce(BigDecimal.ZERO, BigDecimal::add);
                signPlanPrice = quarterSignList.stream().map(s -> s.getEarlySignSumPricePlanC().add(s.getSupplySignSumPricePlanC())).reduce(BigDecimal.ZERO, BigDecimal::add);
                availableNum = earlyNum.add(supplyNum);
                availableArea =  earlyArea.add(supplyArea);
                availablePrice =  earlyPrice.add(supplyPrice);
                supplyAvgPrice = BigDecimalUtils.divBigDecimal(supplyPrice,supplyNum,4);
                signAvgPlanPrice = BigDecimalUtils.divBigDecimal(signPlanPrice,signPlanNum,4);
                availableAvgPrice = BigDecimalUtils.divBigDecimal(availablePrice,availableNum,4);
            }else {
                if(CollectionUtils.isEmpty(quarterEarlyList)){
                    earlyNum = BigDecimal.ZERO;
                    earlyArea = BigDecimal.ZERO;
                    earlyAvgPrice = BigDecimal.ZERO;
                    earlyPrice = BigDecimal.ZERO;
                }else {
                    DmDmPlanSignMonth quarterEarly = quarterEarlyList.get(0);
                    earlyNum = quarterEarly.getEarlyRoomCount();
                    earlyArea = quarterEarly.getEarlyRoomArea();
                    earlyAvgPrice = quarterEarly.getEarlyAvgPrice();
                    earlyPrice = quarterEarly.getEarlySumPrice();
                }
                supplyNum = quarterSignList.stream().map(s -> s.getSupplyRoomCount()).reduce(BigDecimal.ZERO, BigDecimal::add);
                supplyArea = quarterSignList.stream().map(s -> s.getSupplyRoomArea()).reduce(BigDecimal.ZERO, BigDecimal::add);
                supplyPrice = quarterSignList.stream().map(s -> s.getSupplySumPrice()).reduce(BigDecimal.ZERO, BigDecimal::add);

                signPlanNum = quarterSignList.stream().map(s -> s.getEarlySignRoomCountPlan().add(s.getSupplySignRoomCountPlan())).reduce(BigDecimal.ZERO, BigDecimal::add);
                signPlanArea = quarterSignList.stream().map(s -> s.getEarlySignRoomAreaPlan().add(s.getSupplySignRoomAreaPlan())).reduce(BigDecimal.ZERO, BigDecimal::add);
                signPlanPrice = quarterSignList.stream().map(s -> s.getEarlySignSumPricePlan().add(s.getSupplySignSumPricePlan())).reduce(BigDecimal.ZERO, BigDecimal::add);
                availableNum = earlyNum.add(supplyNum);
                availableArea =  earlyArea.add(supplyArea);
                availablePrice =  earlyPrice.add(supplyPrice);
                supplyAvgPrice = BigDecimalUtils.divBigDecimal(supplyPrice,supplyArea,4);
                signAvgPlanPrice = BigDecimalUtils.divBigDecimal(signPlanPrice,signPlanArea,4);
                availableAvgPrice = BigDecimalUtils.divBigDecimal(availablePrice,availableArea,4);
            }

            //<季度综合>计划去化率 = <季度综合>签约计划金额 / <季度综合>可售金额 * 100%
            String syntheticalPlanRemovalRate = BigDecimalUtils.calculatedPercentageA(signPlanPrice, availablePrice);
            vo.setIsParking(isParking);
            vo.setEarlyNum(String.valueOf(earlyNum));
            vo.setEarlyArea(String.valueOf(earlyArea));
            vo.setEarlyAvgPrice(String.valueOf(earlyAvgPrice));
            vo.setEarlyPrice(String.valueOf(earlyPrice));
            vo.setSupplyNum(String.valueOf(supplyNum));
            vo.setSupplyArea(String.valueOf(supplyArea));
            vo.setSupplyAvgPrice(String.valueOf(supplyAvgPrice));
            vo.setSupplyPrice(String.valueOf(supplyPrice));
            vo.setAvailableNum(String.valueOf(availableNum));
            vo.setAvailableArea(String.valueOf(availableArea));
            vo.setAvailableAvgPrice(String.valueOf(availableAvgPrice));
            vo.setAvailablePrice(String.valueOf(availablePrice));
            vo.setSignPlanNum(String.valueOf(signPlanNum));
            vo.setSignPlanArea(String.valueOf(signPlanArea));
            vo.setSignAvgPlanPrice(String.valueOf(signAvgPlanPrice));
            vo.setSignPlanPrice(String.valueOf(signPlanPrice));
            vo.setSyntheticalPlanRemovalRate(syntheticalPlanRemovalRate);

            quarterSignVo.add(vo);
        }
        return quarterSignVo;
    }

    /**
     * 年度签约
     * @param yearSignList
     * @param year
     * @return
     */
    private YearSignVo getYearSignVo(List<DmDmPlanSignYear> yearSignList, String year, int isParking) {
        YearSignVo yearSignVo =new YearSignVo();
        yearSignVo.setYear(year);
        List<DmDmPlanSignYear> yearSigns = yearSignList.stream().filter(s -> s.getYear().equals(year)).collect(Collectors.toList());
        if(CollectionUtils.isEmpty(yearSigns)){
            yearSignVo.initialize();
            return yearSignVo;
        }
        DmDmPlanSignYear yearSign = yearSigns.get(0);
        //<年初存货>套数/车位数
        BigDecimal earlyNum;
        //<年初存货>面积
        BigDecimal earlyArea;
        //<年初存货>均价
        BigDecimal earlyAvgPrice;
        //<年初存货>金额
        BigDecimal earlyPrice;
        //<年初存货>签约实际 套数/车位数
        BigDecimal earlySignActualNum;
        //<年初存货>签约实际面积
        BigDecimal earlySignActualArea;
        //<年初存货>签约实际均价
        BigDecimal earlySignActualAvgPrice;
        //<年初存货>签约实际金额
        BigDecimal earlySignActualPrice;
        //<年度新供>供货计划套数/车位数
        BigDecimal supplyPlanNum;
        //<年度新供>供货计划面积
        BigDecimal supplyPlanArea;
        //<年度新供>供货计划金额
        BigDecimal supplyPlanPrice;
        //<年度新供>供货计划均价
        BigDecimal supplyPlanAvgPrice;
        //<年度新供>供货实际套数/车位数
        BigDecimal supplyActualNum;
        //<年度新供>供货实际面积
        BigDecimal supplyActualArea;
        //<年度新供>供货实际金额
        BigDecimal supplyActualPrice;
        //<年度新供>供货实际均价
        BigDecimal supplyActualAvgPrice;
        //<年度新供>签约实际 套数/车位数
        BigDecimal supplySignActualNum;
        //<年度新供>签约实际面积
        BigDecimal supplySignActualArea;
        //<年度新供>签约实际金额
        BigDecimal supplySignActualPrice;
        //<年度新供>签约实际均价
        BigDecimal supplySignActualAvgPrice;
        //<年度综合>可售 套数/车位数
        BigDecimal syntheticalAvailableNum;
        //<年度综合>可售面积
        BigDecimal syntheticalAvailableArea;
        //<年度综合>可售金额
        BigDecimal syntheticalAvailablePrice;
        //<年度综合>可售均价
        BigDecimal syntheticalAvailableAvgPrice;
        //<年度综合>签约计划 套数/车位数
        BigDecimal syntheticalSignPlanNum;
        //<年度综合>签约计划面积
        BigDecimal syntheticalSignPlanArea;
        //<年度综合>签约计划金额
        BigDecimal syntheticalSignPlanPrice;
        //<年度综合>签约计划均价
        BigDecimal syntheticalSignPlanAvgPrice;
        //<年度综合>签约实际 套数/车位数
        BigDecimal syntheticalSignActualNum;
        //<年度综合>签约实际面积
        BigDecimal syntheticalSignActualArea;
        //<年度综合>签约实际金额
        BigDecimal syntheticalSignActualPrice;
        //<年度综合>签约实际均价
        BigDecimal syntheticalSignActualAvgPrice;
        if(isParking == WhetherEnum.YES.getKey()){
            earlyNum = yearSign.getEarlyNumC();
            earlyArea = yearSign.getEarlyAreaC();
            earlyAvgPrice = yearSign.getEarlyAvgPriceC();
            earlyPrice = yearSign.getEarlyPriceC();
            earlySignActualNum = yearSign.getEarlySignActualNumC();
            earlySignActualArea = yearSign.getEarlySignActualAreaC();
            earlySignActualAvgPrice = yearSign.getEarlySignActualAvgPriceC();
            earlySignActualPrice = yearSign.getEarlySignActualPriceC();
            supplyPlanNum = yearSign.getSupplyPlanNumC();
            supplyPlanArea = yearSign.getSupplyPlanAreaC();
            supplyPlanPrice = yearSign.getSupplyPlanPriceC();
            supplyPlanAvgPrice = yearSign.getSupplyPlanAvgPriceC();
            supplyActualNum = yearSign.getSupplyActualNumC();
            supplyActualArea = yearSign.getSupplyActualAreaC();
            supplyActualPrice = yearSign.getSupplyActualPriceC();
            supplyActualAvgPrice = yearSign.getSupplyActualAvgPriceC();
            supplySignActualNum = yearSign.getSupplySignActualNumC();
            supplySignActualArea = yearSign.getSupplySignActualAreaC();
            supplySignActualPrice = yearSign.getSupplySignActualPriceC();
            supplySignActualAvgPrice = yearSign.getSupplySignActualAvgPriceC();
            syntheticalAvailableNum = yearSign.getSyntheticalAvailableNumC();
            syntheticalAvailableArea = yearSign.getSyntheticalAvailableAreaC();
            syntheticalAvailablePrice = yearSign.getSyntheticalAvailablePriceC();
            syntheticalAvailableAvgPrice = yearSign.getSyntheticalAvailableAvgPriceC();
            syntheticalSignPlanNum = yearSign.getSyntheticalSignPlanNumC();
            syntheticalSignPlanArea = yearSign.getSyntheticalSignPlanAreaC();
            syntheticalSignPlanPrice = yearSign.getSyntheticalSignPlanPriceC();
            syntheticalSignPlanAvgPrice = yearSign.getSyntheticalSignPlanAvgPriceC();
            syntheticalSignActualNum = yearSign.getSyntheticalSignActualNumC();
            syntheticalSignActualArea = yearSign.getSyntheticalSignActualAreaC();
            syntheticalSignActualPrice = yearSign.getSyntheticalSignActualPriceC();
            syntheticalSignActualAvgPrice = yearSign.getSyntheticalSignActualAvgPriceC();
        }else {
            earlyNum = yearSign.getEarlyNum();
            earlyArea = yearSign.getEarlyArea();
            earlyAvgPrice = yearSign.getEarlyAvgPrice();
            earlyPrice = yearSign.getEarlyPrice();
            earlySignActualNum = yearSign.getEarlySignActualNum();
            earlySignActualArea = yearSign.getEarlySignActualArea();
            earlySignActualAvgPrice = yearSign.getEarlySignActualAvgPrice();
            earlySignActualPrice = yearSign.getEarlySignActualPrice();
            supplyPlanNum = yearSign.getSupplyPlanNum();
            supplyPlanArea = yearSign.getSupplyPlanArea();
            supplyPlanPrice = yearSign.getSupplyPlanPrice();
            supplyPlanAvgPrice = yearSign.getSupplyPlanAvgPrice();
            supplyActualNum = yearSign.getSupplyActualNum();
            supplyActualArea = yearSign.getSupplyActualArea();
            supplyActualPrice = yearSign.getSupplyActualPrice();
            supplyActualAvgPrice = yearSign.getSupplyActualAvgPrice();
            supplySignActualNum = yearSign.getSupplySignActualNum();
            supplySignActualArea = yearSign.getSupplySignActualArea();
            supplySignActualPrice = yearSign.getSupplySignActualPrice();
            supplySignActualAvgPrice = yearSign.getSupplySignActualAvgPrice();
            syntheticalAvailableNum = yearSign.getSyntheticalAvailableNum();
            syntheticalAvailableArea = yearSign.getSyntheticalAvailableArea();
            syntheticalAvailablePrice = yearSign.getSyntheticalAvailablePrice();
            syntheticalAvailableAvgPrice = yearSign.getSyntheticalAvailableAvgPrice();
            syntheticalSignPlanNum = yearSign.getSyntheticalSignPlanNum();
            syntheticalSignPlanArea = yearSign.getSyntheticalSignPlanArea();
            syntheticalSignPlanPrice = yearSign.getSyntheticalSignPlanPrice();
            syntheticalSignPlanAvgPrice = yearSign.getSyntheticalSignPlanAvgPrice();
            syntheticalSignActualNum = yearSign.getSyntheticalSignActualNum();
            syntheticalSignActualArea = yearSign.getSyntheticalSignActualArea();
            syntheticalSignActualPrice = yearSign.getSyntheticalSignActualPrice();
            syntheticalSignActualAvgPrice = yearSign.getSyntheticalSignActualAvgPrice();
        }
        //<年初存货>实际去化率
        String earlyActualRemovalRate = BigDecimalUtils.calculatedPercentageA(earlySignActualPrice,earlyPrice);
        //<年度新供>供货完成率
        String supplyFillRate = BigDecimalUtils.calculatedPercentageA(supplyActualPrice,supplyPlanPrice);
        //<年度新供>实际去化率
        String supplyActualRemovalRate = BigDecimalUtils.calculatedPercentageA(supplySignActualPrice,supplyActualPrice);
        //<年度综合>签约完成率 = <年度综合>签约实际金额 / <年度综合>签约计划金额
        String syntheticalSignFillRate = BigDecimalUtils.calculatedPercentageA(syntheticalSignActualPrice,syntheticalSignPlanPrice);
        //<年度综合>实际去化率 = <年度综合>签约实际金额 / <年度综合>可售
        String syntheticalActualRemovalRate = BigDecimalUtils.calculatedPercentageA(syntheticalSignActualPrice,syntheticalAvailablePrice);
        //<年度综合>计划去化率 = <年度综合>签约计划金额 / <年度综合>可售
        String syntheticalPlanRemovalRate = BigDecimalUtils.calculatedPercentageA(syntheticalSignPlanPrice,syntheticalAvailablePrice);


        yearSignVo.setYear(year);
        yearSignVo.setIsParking(isParking);
        yearSignVo.setEarlyNum(String.valueOf(earlyNum));
        yearSignVo.setEarlyArea(String.valueOf(earlyArea));
        yearSignVo.setEarlyAvgPrice(String.valueOf(earlyAvgPrice));
        yearSignVo.setEarlyPrice(String.valueOf(earlyPrice));
        yearSignVo.setEarlySignActualNum(String.valueOf(earlySignActualNum));
        yearSignVo.setEarlySignActualArea(String.valueOf(earlySignActualArea));
        yearSignVo.setEarlySignActualAvgPrice(String.valueOf(earlySignActualAvgPrice));
        yearSignVo.setEarlySignActualPrice(String.valueOf(earlySignActualPrice));
        yearSignVo.setEarlyActualRemovalRate(String.valueOf(earlyActualRemovalRate));
        yearSignVo.setSupplyPlanNum(String.valueOf(supplyPlanNum));
        yearSignVo.setSupplyPlanArea(String.valueOf(supplyPlanArea));
        yearSignVo.setSupplyPlanAvgPrice(String.valueOf(supplyPlanAvgPrice));
        yearSignVo.setSupplyPlanPrice(String.valueOf(supplyPlanPrice));
        yearSignVo.setSupplyActualNum(String.valueOf(supplyActualNum));
        yearSignVo.setSupplyActualArea(String.valueOf(supplyActualArea));
        yearSignVo.setSupplyActualAvgPrice(String.valueOf(supplyActualAvgPrice));
        yearSignVo.setSupplyActualPrice(String.valueOf(supplyActualPrice));
        yearSignVo.setSupplyFillRate(String.valueOf(supplyFillRate));
        yearSignVo.setSupplySignActualNum(String.valueOf(supplySignActualNum));
        yearSignVo.setSupplySignActualArea(String.valueOf(supplySignActualArea));
        yearSignVo.setSupplySignActualAvgPrice(String.valueOf(supplySignActualAvgPrice));
        yearSignVo.setSupplySignActualPrice(String.valueOf(supplySignActualPrice));
        yearSignVo.setSupplyActualRemovalRate(String.valueOf(supplyActualRemovalRate));
        yearSignVo.setSyntheticalAvailableNum(String.valueOf(syntheticalAvailableNum));
        yearSignVo.setSyntheticalAvailableArea(String.valueOf(syntheticalAvailableArea));
        yearSignVo.setSyntheticalAvailableAvgPrice(String.valueOf(syntheticalAvailableAvgPrice));
        yearSignVo.setSyntheticalAvailablePrice(String.valueOf(syntheticalAvailablePrice));
        yearSignVo.setSyntheticalSignPlanNum(String.valueOf(syntheticalSignPlanNum));
        yearSignVo.setSyntheticalSignPlanArea(String.valueOf(syntheticalSignPlanArea));
        yearSignVo.setSyntheticalSignPlanAvgPrice(String.valueOf(syntheticalSignPlanAvgPrice));
        yearSignVo.setSyntheticalSignPlanPrice(String.valueOf(syntheticalSignPlanPrice));
        yearSignVo.setSyntheticalSignActualNum(String.valueOf(syntheticalSignActualNum));
        yearSignVo.setSyntheticalSignActualArea(String.valueOf(syntheticalSignActualArea));
        yearSignVo.setSyntheticalSignActualAvgPrice(String.valueOf(syntheticalSignActualAvgPrice));
        yearSignVo.setSyntheticalSignActualPrice(String.valueOf(syntheticalSignActualPrice));
        yearSignVo.setSyntheticalSignFillRate(String.valueOf(syntheticalSignFillRate));
        yearSignVo.setSyntheticalActualRemovalRate(String.valueOf(syntheticalActualRemovalRate));
        yearSignVo.setSyntheticalPlanRemovalRate(String.valueOf(syntheticalPlanRemovalRate));
        return yearSignVo;
    }

    /**
     * 指定年的月度签约
     * @param monthSignList
     * @param year
     * @return
     */
    private List<MonthSignVo> getMonthSignVo(List<DmDmPlanSignMonth> monthSignList, String year, int isParking) {
        List<MonthSignVo> monthSignVoList = new ArrayList<>();

        List<DmDmPlanSignMonth> monthSigns = monthSignList.stream().filter(s -> s.getSignPlanTime().getYear() == Integer.valueOf(year)).collect(Collectors.toList());

        for (int i = 1; i <= 12 ; i++){
            MonthSignVo monthSignVo =new MonthSignVo();
            int month =i;
            List<DmDmPlanSignMonth> monthSign = monthSigns.stream().filter(s -> s.getSignPlanTime().getMonthValue() == month).collect(Collectors.toList());
            monthSignVo.setYearMonth(LocalDateTimeUtils.toStrYearMonth(Integer.valueOf(year),month));
            if(CollectionUtils.isEmpty(monthSign)){
                monthSignVo.initialize();
                monthSignVoList.add(monthSignVo);
                continue;
            }
            DmDmPlanSignMonth dmMonth = monthSign.get(0);

            //<月初存货>套数/车位数
            BigDecimal earlyNum = BigDecimal.ZERO;
            // <月初存货>面积
            BigDecimal earlyArea = BigDecimal.ZERO;
            //<月初存货>均价
            BigDecimal avgEarlyPrice = BigDecimal.ZERO;
            //<月初存货>金额
            BigDecimal earlyPrice = BigDecimal.ZERO;
            //<月初存货>签约计划 套数/车位数
            BigDecimal earlySignPlanNum = BigDecimal.ZERO;
            //<月初存货>签约计划面积
            BigDecimal earlySignPlanArea = BigDecimal.ZERO;
            // <月初存货>签约计划均价
            BigDecimal earlyAvgSignPlanPrice = BigDecimal.ZERO;
            //<月初存货>签约计划金额
            BigDecimal earlySignPlanPrice = BigDecimal.ZERO;
            //<月初存货>签约实际 套数/车位数
            BigDecimal earlySignActualNum = BigDecimal.ZERO;
            //<月初存货>签约实际面积
            BigDecimal earlySignActualArea = BigDecimal.ZERO;
            //<月初存货>签约实际均价
            BigDecimal earlyAvgSignActualPrice = BigDecimal.ZERO;
            //<月初存货>签约实际金额
            BigDecimal earlySignActualPrice = BigDecimal.ZERO;
            //<月度新供>供货套数/车位数
            BigDecimal supplyNum = BigDecimal.ZERO;
            //<月度新供>供货面积
            BigDecimal supplyArea = BigDecimal.ZERO;
            //<月度新供>供货均价
            BigDecimal supplyAvgPrice = BigDecimal.ZERO;
            //<月度新供>供货金额
            BigDecimal supplyPrice = BigDecimal.ZERO;
            //月度新供>供货计划套数/车位数
            BigDecimal supplyPlanNum = BigDecimal.ZERO;
            //<月度新供>供货计划面积
            BigDecimal supplyPlanArea = BigDecimal.ZERO;
            //<月度新供>供货计划均价
            BigDecimal supplyAvgPlanPrice = BigDecimal.ZERO;
            //<月度新供>供货计划金额
            BigDecimal supplyPlanPrice = BigDecimal.ZERO;
            //<月度新供>供货实际套数/车位数
            BigDecimal supplyActualNum = BigDecimal.ZERO;
            //<月度新供>供货实际面积
            BigDecimal supplyActualArea = BigDecimal.ZERO;
            //<月度新供>供货实际均价
            BigDecimal supplyAvgActualPrice = BigDecimal.ZERO;
            //<月度新供>供货实际金额
            BigDecimal supplyActualPrice = BigDecimal.ZERO;
            //<月度新供>签约计划 套数/车位数
            BigDecimal supplySignPlanNum = BigDecimal.ZERO;
            //<月度新供>签约计划面积
            BigDecimal supplySignPlanArea = BigDecimal.ZERO;
            //<月度新供>签约计划均价
            BigDecimal supplyAvgSignPlanPrice = BigDecimal.ZERO;
            //<月度新供>签约计划金额
            BigDecimal supplySignPlanPrice = BigDecimal.ZERO;
            //<月度新供>签约实际 套数/车位数
            BigDecimal supplySignActualNum = BigDecimal.ZERO;
            //<月度新供>签约实际面积
            BigDecimal supplySignActualArea = BigDecimal.ZERO;
            //<月度新供>签约实际均价
            BigDecimal supplyAvgSignActualPrice = BigDecimal.ZERO;
            //<月度新供>签约实际金额
            BigDecimal supplySignActualPrice = BigDecimal.ZERO;
            if(isParking == WhetherEnum.YES.getKey()){
                earlyNum = dmMonth.getEarlyRoomCountC();
                earlyArea = dmMonth.getEarlyRoomAreaC();
                avgEarlyPrice = dmMonth.getEarlyAvgPriceC();
                earlyPrice = dmMonth.getEarlySumPriceC();
                earlySignPlanNum = dmMonth.getEarlySignRoomCountPlanC();
                earlySignPlanArea = dmMonth.getEarlySignRoomAreaPlanC();
                earlyAvgSignPlanPrice = dmMonth.getEarlySignAvgPricePlanC();
                earlySignPlanPrice = dmMonth.getEarlySignSumPricePlanC();
                earlySignActualNum = dmMonth.getEarlySignRoomCountActualC();
                earlySignActualArea = dmMonth.getEarlySignRoomAreaActualC();
                earlyAvgSignActualPrice = dmMonth.getEarlySignAvgPriceActualC();
                earlySignActualPrice = dmMonth.getEarlySignSumPriceActualC();
                supplyNum = dmMonth.getSupplyRoomCountC();
                supplyArea = dmMonth.getSupplyRoomAreaC();
                supplyAvgPrice = dmMonth.getSupplyAvgPriceC();
                supplyPrice = dmMonth.getSupplySumPriceC();
                supplyPlanNum = dmMonth.getSupplyRoomCountPlanC();
                supplyPlanArea = dmMonth.getSupplyRoomAreaPlanC();
                supplyAvgPlanPrice = dmMonth.getSupplyAvgPricePlanC();
                supplyPlanPrice = dmMonth.getSupplySumPricePlanC();
                supplyActualNum = dmMonth.getSupplyRoomCountActualC();
                supplyActualArea = dmMonth.getSupplyRoomAreaActualC();
                supplyAvgActualPrice = dmMonth.getSupplyAvgPriceActualC();
                supplyActualPrice = dmMonth.getSupplySumPriceActualC();
                supplySignPlanNum = dmMonth.getSupplySignRoomCountPlanC();
                supplySignPlanArea = dmMonth.getSupplySignRoomAreaPlanC();
                supplyAvgSignPlanPrice = dmMonth.getSupplySignAvgPricePlanC();
                supplySignPlanPrice = dmMonth.getSupplySignSumPricePlanC();
                supplySignActualNum = dmMonth.getSupplySignRoomCountActualC();
                supplySignActualArea = dmMonth.getSupplySignRoomAreaActualC();
                supplyAvgSignActualPrice = dmMonth.getSupplySignAvgPriceActualC();
                supplySignActualPrice = dmMonth.getSupplySignSumPriceActualC();
            }else {
                earlyNum = dmMonth.getEarlyRoomCount();
                earlyArea = dmMonth.getEarlyRoomArea();
                avgEarlyPrice = dmMonth.getEarlyAvgPrice();
                earlyPrice = dmMonth.getEarlySumPrice();
                earlySignPlanNum = dmMonth.getEarlySignRoomCountPlan();
                earlySignPlanArea = dmMonth.getEarlySignRoomAreaPlan();
                earlyAvgSignPlanPrice = dmMonth.getEarlySignAvgPricePlan();
                earlySignPlanPrice = dmMonth.getEarlySignSumPricePlan();
                earlySignActualNum = dmMonth.getEarlySignRoomCountActual();
                earlySignActualArea = dmMonth.getEarlySignRoomAreaActual();
                earlyAvgSignActualPrice = dmMonth.getEarlySignAvgPriceActual();
                earlySignActualPrice = dmMonth.getEarlySignSumPriceActual();
                supplyNum = dmMonth.getSupplyRoomCount();
                supplyArea = dmMonth.getSupplyRoomArea();
                supplyAvgPrice = dmMonth.getSupplyAvgPrice();
                supplyPrice = dmMonth.getSupplySumPrice();
                supplyPlanNum = dmMonth.getSupplyRoomCountPlan();
                supplyPlanArea = dmMonth.getSupplyRoomAreaPlan();
                supplyAvgPlanPrice = dmMonth.getSupplyAvgPricePlan();
                supplyPlanPrice = dmMonth.getSupplySumPricePlan();
                supplyActualNum = dmMonth.getSupplyRoomCountActual();
                supplyActualArea = dmMonth.getSupplyRoomAreaActual();
                supplyAvgActualPrice = dmMonth.getSupplyAvgPriceActual();
                supplyActualPrice = dmMonth.getSupplySumPriceActual();
                supplySignPlanNum = dmMonth.getSupplySignRoomCountPlan();
                supplySignPlanArea = dmMonth.getSupplySignRoomAreaPlan();
                supplyAvgSignPlanPrice = dmMonth.getSupplySignAvgPricePlan();
                supplySignPlanPrice = dmMonth.getSupplySignSumPricePlan();
                supplySignActualNum = dmMonth.getSupplySignRoomCountActual();
                supplySignActualArea = dmMonth.getSupplySignRoomAreaActual();
                supplyAvgSignActualPrice = dmMonth.getSupplySignAvgPriceActual();
                supplySignActualPrice = dmMonth.getSupplySignSumPriceActual();
            }

            //<月度综合>可售 套数/车位数 = <月初存货>套数/车位数 + <月度新供>供货金额
            BigDecimal syntheticalAvailableNum = earlyNum.add(supplyNum);
            //<月度综合>可售面积 = <月初存货>面积 + <月度新供>面积
            BigDecimal syntheticalAvailableArea = earlyArea.add(supplyArea);
            //<月度综合>可售金额 = <月初存货>金额 + <月度新供>金额
            BigDecimal syntheticalAvailablePrice = earlyPrice.add(supplyPrice);
            //月度综合>可售均价 = <月初存货>套数/车位数 + <月度新供>供货金额
            BigDecimal syntheticalAvailableAvgPrice;
            if (isParking == WhetherEnum.YES.getKey()) {
                //月度综合>可售均价 = <月度综合>可售金额 / <月度综合>可售车位数
                syntheticalAvailableAvgPrice = BigDecimalUtils.divBigDecimal(syntheticalAvailablePrice, syntheticalAvailableNum, 4);
            } else {
                //月度综合>可售均价 = <月度综合>可售金额 / <月度综合>可售面积
                syntheticalAvailableAvgPrice = BigDecimalUtils.divBigDecimal(syntheticalAvailablePrice, syntheticalAvailableArea, 4);
            }

            //<月度综合>签约计划 套数/车位数 = <月初存货>签约计划 套数/车位数 + <月度新供>签约计划 套数/车位数
            BigDecimal syntheticalSignPlanNum = earlySignPlanNum.add(supplySignPlanNum);
            //<月度综合>签约计划面积 = <月初存货>签约计划面积 + <月度新供>签约计划面积
            BigDecimal syntheticalSignPlanArea = earlySignPlanArea.add(supplySignPlanArea);
            //<月度综合>签约计划金额 = <月初存货>签约计划金额 + <月度新供>签约计划金额
            BigDecimal syntheticalSignPlanPrice = earlySignPlanPrice.add(supplySignPlanPrice);
            //<月度综合>签约计划均价
            BigDecimal syntheticalAvgSignPlanPrice;
            if (isParking == WhetherEnum.YES.getKey()) {
                //月度综合>签约计划均价 = <月度综合>签约计划金额 / <月度综合>签约计划车位数
                syntheticalAvgSignPlanPrice = BigDecimalUtils.divBigDecimal(syntheticalSignPlanPrice, syntheticalSignPlanNum, 4);
            } else {
                //月度综合>签约计划均价 = <月度综合>签约计划金额 / <月度综合>签约计划面积
                syntheticalAvgSignPlanPrice = BigDecimalUtils.divBigDecimal(syntheticalSignPlanPrice, syntheticalSignPlanArea, 4);
            }

            //<月度综合>签约实际 套数/车位数 = <月初存货>签约实际 套数/车位数 + <月度新供>签约实际 套数/车位数
            BigDecimal syntheticalSignActualNum = earlySignActualNum.add(supplySignActualNum);
            //<月度综合>签约实际面积 = <月初存货>签约实际面积 + <月度新供>签约实际面积
            BigDecimal syntheticalSignActualArea = earlySignActualArea.add(supplySignActualArea);
            //<月度综合>签约实际金额 = <月初存货>签约实际金额 + <月度新供>签约实际金额
            BigDecimal syntheticalSignActualPrice = earlySignActualPrice.add(supplySignActualPrice);
            //<月度综合>签约实际均价
            BigDecimal syntheticalAvgSignActualPrice;
            if (isParking == WhetherEnum.YES.getKey()) {
                //月度综合>签约实际均价 = <月度综合>签约实际金额 / <月度综合>签约实际车位数
                syntheticalAvgSignActualPrice = BigDecimalUtils.divBigDecimal(syntheticalSignActualPrice, syntheticalSignActualNum, 4);
            } else {
                //月度综合>签约实际均价 = <月度综合>签约实际金额 / <月度综合>签约实际面积
                syntheticalAvgSignActualPrice = BigDecimalUtils.divBigDecimal(syntheticalSignActualPrice, syntheticalSignActualArea, 4);
            }
            //<月初存货>签约完成率 = <月初存货>签约实际金额 / <月初存货>签约计划金额 * 100%
            String earlySignFillRate = BigDecimalUtils.calculatedPercentageA(earlySignActualPrice, earlySignPlanPrice);
            //<月初存货>实际去化率 = <月初存货>签约实际金额 / <月初存货>金额 * 100%
            String earlyActualRemovalRate = BigDecimalUtils.calculatedPercentageA(earlySignActualPrice, earlyPrice);
            //<月初存货>计划去化率 = <月初存货>签约计划金额 / <月初存货>金额 * 100%
            String earlyPlanRemovalRate = BigDecimalUtils.calculatedPercentageA(earlySignPlanPrice, earlyPrice);
            //<月度新供>供货完成率 = <月度新供>供货实际金额 / <月度新供>供货计划金额 * 100%
            String supplyFillRate = BigDecimalUtils.calculatedPercentageA(supplyActualPrice, supplyPlanPrice);
            //<月度新供>签约完成率 = <月度新供>签约实际金额 / <月度新供>签约计划金额 * 100%
            String supplySignFillRate = BigDecimalUtils.calculatedPercentageA(supplySignActualPrice, supplySignPlanPrice);
            //<月度新供>实际去化率 = <月度新供>签约实际金额 / <月度新供>供货实际金额 * 100%
            String supplyActualRemovalRate = BigDecimalUtils.calculatedPercentageA(supplySignActualPrice, supplyActualPrice);
            //<月度新供>计划去化率 = <月度新供>签约计划金额 / <月度新供>供货计划金额 * 100%
            String supplyPlanRemovalRate = BigDecimalUtils.calculatedPercentageA(supplySignPlanPrice, supplyPlanPrice);
            //<月度综合>签约完成率 = <月度综合>签约实际金额 / <月度综合>签约计划金额 * 100%
            String syntheticalSignFillRate = BigDecimalUtils.calculatedPercentageA(syntheticalSignActualPrice, syntheticalSignPlanPrice);
            //<月度综合>实际去化率 = <月度综合>签约实际金额 / <月度综合>可售金额 * 100%
            String syntheticalActualRemovalRate = BigDecimalUtils.calculatedPercentageA(syntheticalSignActualPrice, syntheticalAvailablePrice);
            //<月度综合>计划去化率 = <月度综合>签约计划金额 / <月度综合>可售金额 * 100%
            String syntheticalPlanRemovalRate = BigDecimalUtils.calculatedPercentageA(syntheticalSignPlanPrice, syntheticalAvailablePrice);

            monthSignVo.setIsParking(isParking);
            monthSignVo.setEarlyNum(String.valueOf(earlyNum));
            monthSignVo.setEarlyArea(String.valueOf(earlyArea));
            monthSignVo.setAvgEarlyPrice(String.valueOf(avgEarlyPrice));
            monthSignVo.setEarlyPrice(String.valueOf(earlyPrice));
            monthSignVo.setEarlySignPlanNum(String.valueOf(earlySignPlanNum));
            monthSignVo.setEarlySignPlanArea(String.valueOf(earlySignPlanArea));
            monthSignVo.setEarlyAvgSignPlanPrice(String.valueOf(earlyAvgSignPlanPrice));
            monthSignVo.setEarlySignPlanPrice(String.valueOf(earlySignPlanPrice));
            monthSignVo.setEarlySignActualNum(String.valueOf(earlySignActualNum));
            monthSignVo.setEarlySignActualArea(String.valueOf(earlySignActualArea));
            monthSignVo.setEarlyAvgSignActualPrice(String.valueOf(earlyAvgSignActualPrice));
            monthSignVo.setEarlySignActualPrice(String.valueOf(earlySignActualPrice));
            monthSignVo.setEarlySignFillRate(earlySignFillRate);
            monthSignVo.setEarlyActualRemovalRate(earlyActualRemovalRate);
            monthSignVo.setEarlyPlanRemovalRate(earlyPlanRemovalRate);
            monthSignVo.setSupplyPlanNum(String.valueOf(supplyPlanNum));
            monthSignVo.setSupplyPlanArea(String.valueOf(supplyPlanArea));
            monthSignVo.setSupplyAvgPlanPrice(String.valueOf(supplyAvgPlanPrice));
            monthSignVo.setSupplyPlanPrice(String.valueOf(supplyPlanPrice));
            monthSignVo.setSupplyActualNum(String.valueOf(supplyActualNum));
            monthSignVo.setSupplyActualArea(String.valueOf(supplyActualArea));
            monthSignVo.setSupplyAvgActualPrice(String.valueOf(supplyAvgActualPrice));
            monthSignVo.setSupplyActualPrice(String.valueOf(supplyActualPrice));
            monthSignVo.setSupplyFillRate(supplyFillRate);
            monthSignVo.setSupplySignPlanNum(String.valueOf(supplySignPlanNum));
            monthSignVo.setSupplySignPlanArea(String.valueOf(supplySignPlanArea));
            monthSignVo.setSupplyAvgSignPlanPrice(String.valueOf(supplyAvgSignPlanPrice));
            monthSignVo.setSupplySignPlanPrice(String.valueOf(supplySignPlanPrice));
            monthSignVo.setSupplySignActualNum(String.valueOf(supplySignActualNum));
            monthSignVo.setSupplySignActualArea(String.valueOf(supplySignActualArea));
            monthSignVo.setSupplyAvgSignActualPrice(String.valueOf(supplyAvgSignActualPrice));
            monthSignVo.setSupplySignActualPrice(String.valueOf(supplySignActualPrice));
            monthSignVo.setSupplySignFillRate(supplySignFillRate);
            monthSignVo.setSupplyActualRemovalRate(supplyActualRemovalRate);
            monthSignVo.setSupplyPlanRemovalRate(supplyPlanRemovalRate);
            monthSignVo.setSyntheticalAvailableNum(String.valueOf(syntheticalAvailableNum));
            monthSignVo.setSyntheticalAvailableArea(String.valueOf(syntheticalAvailableArea));
            monthSignVo.setSyntheticalAvailableAvgPrice(String.valueOf(syntheticalAvailableAvgPrice));
            monthSignVo.setSyntheticalAvailablePrice(String.valueOf(syntheticalAvailablePrice));
            monthSignVo.setSyntheticalSignPlanNum(String.valueOf(syntheticalSignPlanNum));
            monthSignVo.setSyntheticalSignPlanArea(String.valueOf(syntheticalSignPlanArea));
            monthSignVo.setSyntheticalAvgSignPlanPrice(String.valueOf(syntheticalAvgSignPlanPrice));
            monthSignVo.setSyntheticalSignPlanPrice(String.valueOf(syntheticalSignPlanPrice));
            monthSignVo.setSyntheticalSignActualNum(String.valueOf(syntheticalSignActualNum));
            monthSignVo.setSyntheticalSignActualArea(String.valueOf(syntheticalSignActualArea));
            monthSignVo.setSyntheticalAvgSignActualPrice(String.valueOf(syntheticalAvgSignActualPrice));
            monthSignVo.setSyntheticalSignActualPrice(String.valueOf(syntheticalSignActualPrice));
            monthSignVo.setSyntheticalSignFillRate(syntheticalSignFillRate);
            monthSignVo.setSyntheticalActualRemovalRate(syntheticalActualRemovalRate);
            monthSignVo.setSyntheticalPlanRemovalRate(syntheticalPlanRemovalRate);
            monthSignVoList.add(monthSignVo);
        }
        return monthSignVoList;
    }

    /**
     * 计算当年以前签约
     * @param yearSignList
     * @param year
     * @return
     */
    private PastYearVo getPastYearVo (List < DmDmPlanSignYear > yearSignList, String year,int isParking){
        PastYearVo pastYearVo = new PastYearVo();

        List<DmDmPlanSignYear> yearSigns = yearSignList.stream().filter(s -> Integer.valueOf(s.getYear()) < Integer.valueOf(year)).collect(Collectors.toList());

        //总可售货值-套数
        BigDecimal availableNum ;
        //总可售货值-面积
        BigDecimal availableArea;
        //总可售货值-均价
        BigDecimal availableAvgPrice;
        //总可售货值-金额
        BigDecimal availablePrice;
        //签约实际-套数
        BigDecimal signActualNum;
        //签约实际-面积
        BigDecimal signActualArea;
        //签约实际-均价
        BigDecimal signAvgActualPrice;
        //签约实际-金额
        BigDecimal signActualPrice;
        //签约计划-套数
        BigDecimal signPlanNum;
        //签约计划-面积
        BigDecimal signPlanArea;
        //签约计划-均价
        BigDecimal signAvgPlanPrice;
        //签约计划-金额
        BigDecimal signPlanPrice;

        if(isParking == WhetherEnum.YES.getKey()){
            availableNum = yearSigns.stream().map(s -> s.getSupplyActualNumC()).reduce(BigDecimal.ZERO, BigDecimal::add);
            availableArea = yearSigns.stream().map(s -> s.getSupplyActualAreaC()).reduce(BigDecimal.ZERO, BigDecimal::add);
            availablePrice = yearSigns.stream().map(s -> s.getSupplyActualPriceC()).reduce(BigDecimal.ZERO, BigDecimal::add);
            signActualNum = yearSigns.stream().map(s -> s.getSyntheticalSignActualNumC()).reduce(BigDecimal.ZERO, BigDecimal::add);
            signActualArea = yearSigns.stream().map(s -> s.getSyntheticalSignActualAreaC()).reduce(BigDecimal.ZERO, BigDecimal::add);
            signActualPrice = yearSigns.stream().map(s -> s.getSyntheticalSignActualPriceC()).reduce(BigDecimal.ZERO, BigDecimal::add);
            signPlanNum = yearSigns.stream().map(s -> s.getSyntheticalSignPlanNumC()).reduce(BigDecimal.ZERO, BigDecimal::add);
            signPlanArea = yearSigns.stream().map(s -> s.getSyntheticalSignPlanAreaC()).reduce(BigDecimal.ZERO, BigDecimal::add);
            signPlanPrice = yearSigns.stream().map(s -> s.getSyntheticalSignPlanPriceC()).reduce(BigDecimal.ZERO, BigDecimal::add);
            availableAvgPrice = BigDecimalUtils.divBigDecimal(availablePrice,availableNum,4);
            signAvgActualPrice = BigDecimalUtils.divBigDecimal(signActualPrice,signActualNum,4);
            signAvgPlanPrice = BigDecimalUtils.divBigDecimal(signPlanPrice,signPlanNum,4);
        }else {
            availableNum = yearSigns.stream().map(s -> s.getSupplyActualNum()).reduce(BigDecimal.ZERO, BigDecimal::add);
            availableArea = yearSigns.stream().map(s -> s.getSupplyActualArea()).reduce(BigDecimal.ZERO, BigDecimal::add);
            availablePrice = yearSigns.stream().map(s -> s.getSupplyActualPrice()).reduce(BigDecimal.ZERO, BigDecimal::add);
            signActualNum = yearSigns.stream().map(s -> s.getSyntheticalSignActualNum()).reduce(BigDecimal.ZERO, BigDecimal::add);
            signActualArea = yearSigns.stream().map(s -> s.getSyntheticalSignActualArea()).reduce(BigDecimal.ZERO, BigDecimal::add);
            signActualPrice = yearSigns.stream().map(s -> s.getSyntheticalSignActualPrice()).reduce(BigDecimal.ZERO, BigDecimal::add);
            signPlanNum = yearSigns.stream().map(s -> s.getSyntheticalSignPlanNum()).reduce(BigDecimal.ZERO, BigDecimal::add);
            signPlanArea = yearSigns.stream().map(s -> s.getSyntheticalSignPlanArea()).reduce(BigDecimal.ZERO, BigDecimal::add);
            signPlanPrice = yearSigns.stream().map(s -> s.getSyntheticalSignPlanPrice()).reduce(BigDecimal.ZERO, BigDecimal::add);
            availableAvgPrice = BigDecimalUtils.divBigDecimal(availablePrice,availableArea,4);
            signAvgActualPrice = BigDecimalUtils.divBigDecimal(signActualPrice,signActualArea,4);
            signAvgPlanPrice = BigDecimalUtils.divBigDecimal(signPlanPrice,signPlanArea,4);
        }

        // 签约完成率(签约实际金额 / 签约计划金额)
        String signFillRate = BigDecimalUtils.calculatedPercentageA(signActualPrice, signPlanPrice);
        // 实际去化率(签约实际金额 / 总可售金额)
        String actualRemovalRate = BigDecimalUtils.calculatedPercentageA(signActualPrice, availablePrice);
        // 计划去化率（签约计划金额 / 总可售金额）
        String planRemovalRate = BigDecimalUtils.calculatedPercentageA(signPlanPrice, availablePrice);

        pastYearVo.setIsParking(isParking);
        pastYearVo.setAvailableNum(String.valueOf(availableNum));
        pastYearVo.setAvailableArea(String.valueOf(availableArea));
        pastYearVo.setAvailableAvgPrice(String.valueOf(availableAvgPrice));
        pastYearVo.setAvailablePrice(String.valueOf(availablePrice));
        pastYearVo.setSignActualNum(String.valueOf(signActualNum));
        pastYearVo.setSignActualArea(String.valueOf(signActualArea));
        pastYearVo.setSignAvgActualPrice(String.valueOf(signAvgActualPrice));
        pastYearVo.setSignActualPrice(String.valueOf(signActualPrice));
        pastYearVo.setSignPlanNum(String.valueOf(signPlanNum));
        pastYearVo.setSignPlanArea(String.valueOf(signPlanArea));
        pastYearVo.setSignAvgPlanPrice(String.valueOf(signAvgPlanPrice));
        pastYearVo.setSignPlanPrice(String.valueOf(signPlanPrice));
        pastYearVo.setSignFillRate(signFillRate);
        pastYearVo.setActualRemovalRate(actualRemovalRate);
        pastYearVo.setPlanRemovalRate(planRemovalRate);

        return pastYearVo;
    }

    //获取级联
    private List<SignCascaderBO> toSignCascaderBO(String str, List<DmDmPlanSignMonth> dmDmPlanSignMonthList,String type) {
        List<SignCascaderBO> signCascaderBOList = new ArrayList<>();
        SignCascaderBO signCascaderBO = new SignCascaderBO();

        signCascaderBO.setType(type);
        if(type.equals("proProduct")){
            signCascaderBO.setPid(dmDmPlanSignMonthList.get(0).getVersionId());
            signCascaderBO.setId(signCascaderBO.getPid()+str);
        }else if(type.equals("stage")){
            signCascaderBO.setPid(dmDmPlanSignMonthList.get(0).getProjectId());
            signCascaderBO.setId(str);
        }else if(type.equals("project")){
            signCascaderBO.setPid(dmDmPlanSignMonthList.get(0).getCityCompanyId());
            signCascaderBO.setId(str);
        }

        signCascaderBOList.add(signCascaderBO);
        return signCascaderBOList;
    }

    //获取级联
    private List<SignCascaderBO> toSignCascaderBO(List<ProjectByStagesDto> projectDtos) {
        List<SignCascaderBO> signCascaderBOList = new ArrayList<>();

        for (ProjectByStagesDto dto : projectDtos){
            SignCascaderBO signCascaderBO = new SignCascaderBO();
            signCascaderBO.setId(dto.getOrgdepid());
            signCascaderBO.setPid(dto.getParentOrgid());
            signCascaderBO.setType(dto.getHrOrgType());
            signCascaderBO.setName(dto.getOrgname());
            signCascaderBOList.add(signCascaderBO);
        }
        return signCascaderBOList;
    }

    /**
     * 修改数值格式 金额单位万元
     * @param voList
     */
    @Override
    public void updateDmAnalyticalVoAccuracy(List<DmAnalyticalVo> voList) {

        for (DmAnalyticalVo vo:voList){
            PastYearVo supplyAndSignVo = vo.getPastYearVo();
            if(null != vo.getProductName()){
                supplyAndSignVo.setAvailableNum(NumberUtils.accuracyBigDecimalToStr(supplyAndSignVo.getAvailableNum(),2));
                supplyAndSignVo.setAvailableArea(NumberUtils.accuracyBigDecimalToStr(supplyAndSignVo.getAvailableArea(),2));
                supplyAndSignVo.setAvailableAvgPrice(NumberUtils.accuracyBigDecimalToStr(supplyAndSignVo.getAvailableAvgPrice(),0));
                supplyAndSignVo.setAvailablePrice(NumberUtils.fmtToWan(supplyAndSignVo.getAvailablePrice()));
                supplyAndSignVo.setSignPlanNum(NumberUtils.accuracyBigDecimalToStr(supplyAndSignVo.getSignPlanNum(),2));
                supplyAndSignVo.setSignPlanArea(NumberUtils.accuracyBigDecimalToStr(supplyAndSignVo.getSignPlanArea(),2));
                supplyAndSignVo.setSignAvgPlanPrice(NumberUtils.accuracyBigDecimalToStr(supplyAndSignVo.getSignAvgPlanPrice(),0));
                supplyAndSignVo.setSignPlanPrice(NumberUtils.fmtToWan(supplyAndSignVo.getSignPlanPrice()));
                supplyAndSignVo.setSignActualNum(NumberUtils.accuracyBigDecimalToStr(supplyAndSignVo.getSignActualNum(),2));
                supplyAndSignVo.setSignActualArea(NumberUtils.accuracyBigDecimalToStr(supplyAndSignVo.getSignActualArea(),2));
                supplyAndSignVo.setSignAvgActualPrice(NumberUtils.accuracyBigDecimalToStr(supplyAndSignVo.getSignAvgActualPrice(),0));
                supplyAndSignVo.setSignActualPrice(NumberUtils.fmtToWan(supplyAndSignVo.getSignActualPrice()));

                List<MonthSignVo> monthSignVoList = vo.getMonthSignVo();
                for (MonthSignVo monthSignVo:monthSignVoList){
                    monthSignVo.setEarlyNum(NumberUtils.accuracyBigDecimalToStr(monthSignVo.getEarlyNum(),2));
                    monthSignVo.setEarlyArea(NumberUtils.accuracyBigDecimalToStr(monthSignVo.getEarlyArea(),2));
                    monthSignVo.setAvgEarlyPrice(NumberUtils.accuracyBigDecimalToStr(monthSignVo.getAvgEarlyPrice(),0));
                    monthSignVo.setEarlyPrice(NumberUtils.fmtToWan(monthSignVo.getEarlyPrice()));
                    monthSignVo.setEarlySignPlanNum(NumberUtils.accuracyBigDecimalToStr(monthSignVo.getEarlySignPlanNum(),2));
                    monthSignVo.setEarlySignPlanArea(NumberUtils.accuracyBigDecimalToStr(monthSignVo.getEarlySignPlanArea(),2));
                    monthSignVo.setEarlyAvgSignPlanPrice(NumberUtils.accuracyBigDecimalToStr(monthSignVo.getEarlyAvgSignPlanPrice(),0));
                    monthSignVo.setEarlySignPlanPrice(NumberUtils.fmtToWan(monthSignVo.getEarlySignPlanPrice()));
                    monthSignVo.setEarlySignActualNum(NumberUtils.accuracyBigDecimalToStr(monthSignVo.getEarlySignActualNum(),2));
                    monthSignVo.setEarlySignActualArea(NumberUtils.accuracyBigDecimalToStr(monthSignVo.getEarlySignActualArea(),2));
                    monthSignVo.setEarlyAvgSignActualPrice(NumberUtils.accuracyBigDecimalToStr(monthSignVo.getEarlyAvgSignActualPrice(),0));
                    monthSignVo.setEarlySignActualPrice(NumberUtils.fmtToWan(monthSignVo.getEarlySignActualPrice()));
                    monthSignVo.setSupplyPlanNum(NumberUtils.accuracyBigDecimalToStr(monthSignVo.getSupplyPlanNum(),2));
                    monthSignVo.setSupplyPlanArea(NumberUtils.accuracyBigDecimalToStr(monthSignVo.getSupplyPlanArea(),2));
                    monthSignVo.setSupplyAvgPlanPrice(NumberUtils.accuracyBigDecimalToStr(monthSignVo.getSupplyAvgPlanPrice(),0));
                    monthSignVo.setSupplyPlanPrice(NumberUtils.fmtToWan(monthSignVo.getSupplyPlanPrice()));
                    monthSignVo.setSupplyActualNum(NumberUtils.accuracyBigDecimalToStr(monthSignVo.getSupplyActualNum(),2));
                    monthSignVo.setSupplyActualArea(NumberUtils.accuracyBigDecimalToStr(monthSignVo.getSupplyActualArea(),2));
                    monthSignVo.setSupplyAvgActualPrice(NumberUtils.accuracyBigDecimalToStr(monthSignVo.getSupplyAvgActualPrice(),0));
                    monthSignVo.setSupplyActualPrice(NumberUtils.fmtToWan(monthSignVo.getSupplyActualPrice()));
                    monthSignVo.setSupplySignPlanNum(NumberUtils.accuracyBigDecimalToStr(monthSignVo.getSupplySignPlanNum(),2));
                    monthSignVo.setSupplySignPlanArea(NumberUtils.accuracyBigDecimalToStr(monthSignVo.getSupplySignPlanArea(),2));
                    monthSignVo.setSupplyAvgSignPlanPrice(NumberUtils.accuracyBigDecimalToStr(monthSignVo.getSupplyAvgSignPlanPrice(),0));
                    monthSignVo.setSupplySignPlanPrice(NumberUtils.fmtToWan(monthSignVo.getSupplySignPlanPrice()));
                    monthSignVo.setSupplySignActualNum(NumberUtils.accuracyBigDecimalToStr(monthSignVo.getSupplySignActualNum(),2));
                    monthSignVo.setSupplySignActualArea(NumberUtils.accuracyBigDecimalToStr(monthSignVo.getSupplySignActualArea(),2));
                    monthSignVo.setSupplyAvgSignActualPrice(NumberUtils.accuracyBigDecimalToStr(monthSignVo.getSupplyAvgSignActualPrice(),0));
                    monthSignVo.setSupplySignActualPrice(NumberUtils.fmtToWan(monthSignVo.getSupplySignActualPrice()));
                    monthSignVo.setSyntheticalAvailableNum(NumberUtils.accuracyBigDecimalToStr(monthSignVo.getSyntheticalAvailableNum(),2));
                    monthSignVo.setSyntheticalAvailableArea(NumberUtils.accuracyBigDecimalToStr(monthSignVo.getSyntheticalAvailableArea(),2));
                    monthSignVo.setSyntheticalAvailableAvgPrice(NumberUtils.accuracyBigDecimalToStr(monthSignVo.getSyntheticalAvailableAvgPrice(),0));
                    monthSignVo.setSyntheticalAvailablePrice(NumberUtils.fmtToWan(monthSignVo.getSyntheticalAvailablePrice()));
                    monthSignVo.setSyntheticalSignPlanNum(NumberUtils.accuracyBigDecimalToStr(monthSignVo.getSyntheticalSignPlanNum(),2));
                    monthSignVo.setSyntheticalSignPlanArea(NumberUtils.accuracyBigDecimalToStr(monthSignVo.getSyntheticalSignPlanArea(),2));
                    monthSignVo.setSyntheticalAvgSignPlanPrice(NumberUtils.accuracyBigDecimalToStr(monthSignVo.getSyntheticalAvgSignPlanPrice(),0));
                    monthSignVo.setSyntheticalSignPlanPrice(NumberUtils.fmtToWan(monthSignVo.getSyntheticalSignPlanPrice()));
                    monthSignVo.setSyntheticalSignActualNum(NumberUtils.accuracyBigDecimalToStr(monthSignVo.getSyntheticalSignActualNum(),2));
                    monthSignVo.setSyntheticalSignActualArea(NumberUtils.accuracyBigDecimalToStr(monthSignVo.getSyntheticalSignActualArea(),2));
                    monthSignVo.setSyntheticalAvgSignActualPrice(NumberUtils.accuracyBigDecimalToStr(monthSignVo.getSyntheticalAvgSignActualPrice(),0));
                    monthSignVo.setSyntheticalSignActualPrice(NumberUtils.fmtToWan(monthSignVo.getSyntheticalSignActualPrice()));
                }

                YearSignVo yearSignVo = vo.getYearSignVo();
                yearSignVo.setEarlyNum(NumberUtils.accuracyBigDecimalToStr(yearSignVo.getEarlyNum(),2));
                yearSignVo.setEarlyArea(NumberUtils.accuracyBigDecimalToStr(yearSignVo.getEarlyArea(),2));
                yearSignVo.setEarlyAvgPrice(NumberUtils.accuracyBigDecimalToStr(yearSignVo.getEarlyAvgPrice(),0));
                yearSignVo.setEarlyPrice(NumberUtils.fmtToWan(yearSignVo.getEarlyPrice()));
                yearSignVo.setEarlySignActualNum(NumberUtils.accuracyBigDecimalToStr(yearSignVo.getEarlySignActualNum(),2));
                yearSignVo.setEarlySignActualArea(NumberUtils.accuracyBigDecimalToStr(yearSignVo.getEarlySignActualArea(),2));
                yearSignVo.setEarlySignActualAvgPrice(NumberUtils.accuracyBigDecimalToStr(yearSignVo.getEarlySignActualAvgPrice(),0));
                yearSignVo.setEarlySignActualPrice(NumberUtils.fmtToWan(yearSignVo.getEarlySignActualPrice()));
                yearSignVo.setSupplyPlanNum(NumberUtils.accuracyBigDecimalToStr(yearSignVo.getSupplyPlanNum(),2));
                yearSignVo.setSupplyPlanArea(NumberUtils.accuracyBigDecimalToStr(yearSignVo.getSupplyPlanArea(),2));
                yearSignVo.setSupplyPlanAvgPrice(NumberUtils.accuracyBigDecimalToStr(yearSignVo.getSupplyPlanAvgPrice(),0));
                yearSignVo.setSupplyPlanPrice(NumberUtils.fmtToWan(yearSignVo.getSupplyPlanPrice()));
                yearSignVo.setSupplyActualNum(NumberUtils.accuracyBigDecimalToStr(yearSignVo.getSupplyActualNum(),2));
                yearSignVo.setSupplyActualArea(NumberUtils.accuracyBigDecimalToStr(yearSignVo.getSupplyActualArea(),2));
                yearSignVo.setSupplyActualAvgPrice(NumberUtils.accuracyBigDecimalToStr(yearSignVo.getSupplyActualAvgPrice(),0));
                yearSignVo.setSupplyActualPrice(NumberUtils.fmtToWan(yearSignVo.getSupplyActualPrice()));
                yearSignVo.setSupplySignActualNum(NumberUtils.accuracyBigDecimalToStr(yearSignVo.getSupplySignActualNum(),2));
                yearSignVo.setSupplySignActualArea(NumberUtils.accuracyBigDecimalToStr(yearSignVo.getSupplySignActualArea(),2));
                yearSignVo.setSupplySignActualAvgPrice(NumberUtils.accuracyBigDecimalToStr(yearSignVo.getSupplySignActualAvgPrice(),0));
                yearSignVo.setSupplySignActualPrice(NumberUtils.fmtToWan(yearSignVo.getSupplySignActualPrice()));
                yearSignVo.setSyntheticalAvailableNum(NumberUtils.accuracyBigDecimalToStr(yearSignVo.getSyntheticalAvailableNum(),2));
                yearSignVo.setSyntheticalAvailableArea(NumberUtils.accuracyBigDecimalToStr(yearSignVo.getSyntheticalAvailableArea(),2));
                yearSignVo.setSyntheticalAvailableAvgPrice(NumberUtils.accuracyBigDecimalToStr(yearSignVo.getSyntheticalAvailableAvgPrice(),0));
                yearSignVo.setSyntheticalAvailablePrice(NumberUtils.fmtToWan(yearSignVo.getSyntheticalAvailablePrice()));
                yearSignVo.setSyntheticalSignPlanNum(NumberUtils.accuracyBigDecimalToStr(yearSignVo.getSyntheticalSignPlanNum(),2));
                yearSignVo.setSyntheticalSignPlanArea(NumberUtils.accuracyBigDecimalToStr(yearSignVo.getSyntheticalSignPlanArea(),2));
                yearSignVo.setSyntheticalSignPlanAvgPrice(NumberUtils.accuracyBigDecimalToStr(yearSignVo.getSyntheticalSignPlanAvgPrice(),0));
                yearSignVo.setSyntheticalSignPlanPrice(NumberUtils.fmtToWan(yearSignVo.getSyntheticalSignPlanPrice()));
                yearSignVo.setSyntheticalSignActualNum(NumberUtils.accuracyBigDecimalToStr(yearSignVo.getSyntheticalSignActualNum(),2));
                yearSignVo.setSyntheticalSignActualArea(NumberUtils.accuracyBigDecimalToStr(yearSignVo.getSyntheticalSignActualArea(),2));
                yearSignVo.setSyntheticalSignActualAvgPrice(NumberUtils.accuracyBigDecimalToStr(yearSignVo.getSyntheticalSignActualAvgPrice(),0));
                yearSignVo.setSyntheticalSignActualPrice(NumberUtils.fmtToWan(yearSignVo.getSyntheticalSignActualPrice()));

                List<QuarterSignVo> quarterSignVoList = vo.getQuarterSignVo();
                for (QuarterSignVo quarterSignVo :quarterSignVoList){
                    quarterSignVo.setEarlyNum(NumberUtils.accuracyBigDecimalToStr(quarterSignVo.getEarlyNum(),2));
                    quarterSignVo.setEarlyArea(NumberUtils.accuracyBigDecimalToStr(quarterSignVo.getEarlyArea(),2));
                    quarterSignVo.setEarlyAvgPrice(NumberUtils.accuracyBigDecimalToStr(quarterSignVo.getEarlyAvgPrice(),0));
                    quarterSignVo.setEarlyPrice(NumberUtils.fmtToWan(quarterSignVo.getEarlyPrice()));
                    quarterSignVo.setSupplyNum(NumberUtils.accuracyBigDecimalToStr(quarterSignVo.getSupplyNum(),2));
                    quarterSignVo.setSupplyArea(NumberUtils.accuracyBigDecimalToStr(quarterSignVo.getSupplyArea(),2));
                    quarterSignVo.setSupplyAvgPrice(NumberUtils.accuracyBigDecimalToStr(quarterSignVo.getSupplyAvgPrice(),0));
                    quarterSignVo.setSupplyPrice(NumberUtils.fmtToWan(quarterSignVo.getSupplyPrice()));
                    quarterSignVo.setAvailableNum(NumberUtils.accuracyBigDecimalToStr(quarterSignVo.getAvailableNum(),2));
                    quarterSignVo.setAvailableArea(NumberUtils.accuracyBigDecimalToStr(quarterSignVo.getAvailableArea(),2));
                    quarterSignVo.setAvailableAvgPrice(NumberUtils.accuracyBigDecimalToStr(quarterSignVo.getAvailableAvgPrice(),0));
                    quarterSignVo.setAvailablePrice(NumberUtils.fmtToWan(quarterSignVo.getAvailablePrice()));
                    quarterSignVo.setSignPlanNum(NumberUtils.accuracyBigDecimalToStr(quarterSignVo.getSignPlanNum(),2));
                    quarterSignVo.setSignPlanArea(NumberUtils.accuracyBigDecimalToStr(quarterSignVo.getSignPlanArea(),2));
                    quarterSignVo.setSignAvgPlanPrice(NumberUtils.accuracyBigDecimalToStr(quarterSignVo.getSignAvgPlanPrice(),0));
                    quarterSignVo.setSignPlanPrice(NumberUtils.fmtToWan(quarterSignVo.getSignPlanPrice()));
                }

                List<YearTotalVo> yearTotalVoList = vo.getYearTotalVo();
                for (YearTotalVo yearTotalVo : yearTotalVoList){
                    yearTotalVo.setEarlyNum(NumberUtils.accuracyBigDecimalToStr(yearTotalVo.getEarlyNum(),2));
                    yearTotalVo.setEarlyArea(NumberUtils.accuracyBigDecimalToStr(yearTotalVo.getEarlyArea(),2));
                    yearTotalVo.setEarlyAvgPrice(NumberUtils.accuracyBigDecimalToStr(yearTotalVo.getEarlyAvgPrice(),0));
                    yearTotalVo.setEarlyPrice(NumberUtils.fmtToWan(yearTotalVo.getEarlyPrice()));
                    yearTotalVo.setSupplyNum(NumberUtils.accuracyBigDecimalToStr(yearTotalVo.getSupplyNum(),2));
                    yearTotalVo.setSupplyArea(NumberUtils.accuracyBigDecimalToStr(yearTotalVo.getSupplyArea(),2));
                    yearTotalVo.setSupplyAvgPrice(NumberUtils.accuracyBigDecimalToStr(yearTotalVo.getSupplyAvgPrice(),0));
                    yearTotalVo.setSupplyPrice(NumberUtils.fmtToWan(yearTotalVo.getSupplyPrice()));
                    yearTotalVo.setAvailableNum(NumberUtils.accuracyBigDecimalToStr(yearTotalVo.getAvailableNum(),2));
                    yearTotalVo.setAvailableArea(NumberUtils.accuracyBigDecimalToStr(yearTotalVo.getAvailableArea(),2));
                    yearTotalVo.setAvailableAvgPrice(NumberUtils.accuracyBigDecimalToStr(yearTotalVo.getAvailableAvgPrice(),0));
                    yearTotalVo.setAvailablePrice(NumberUtils.fmtToWan(yearTotalVo.getAvailablePrice()));
                    yearTotalVo.setSignPlanNum(NumberUtils.accuracyBigDecimalToStr(yearTotalVo.getSignPlanNum(),2));
                    yearTotalVo.setSignPlanArea(NumberUtils.accuracyBigDecimalToStr(yearTotalVo.getSignPlanArea(),2));
                    yearTotalVo.setSignAvgPlanPrice(NumberUtils.accuracyBigDecimalToStr(yearTotalVo.getSignAvgPlanPrice(),0));
                    yearTotalVo.setSignPlanPrice(NumberUtils.fmtToWan(yearTotalVo.getSignPlanPrice()));
                }
            }else {
                supplyAndSignVo.setAvailableNum(NumberUtils.updateBigAccuracy(supplyAndSignVo.getAvailableNum(),2));
                supplyAndSignVo.setAvailableArea(NumberUtils.accuracyBigDecimalToStr(supplyAndSignVo.getAvailableArea(),2));
                supplyAndSignVo.setAvailableAvgPrice(NumberUtils.updateBigAccuracy(supplyAndSignVo.getAvailableAvgPrice(),0));
                supplyAndSignVo.setAvailablePrice(NumberUtils.priceToWanAndMicrometer(supplyAndSignVo.getAvailablePrice()));
                supplyAndSignVo.setSignPlanNum(NumberUtils.updateBigAccuracy(supplyAndSignVo.getSignPlanNum(),2));
                supplyAndSignVo.setSignPlanArea(NumberUtils.accuracyBigDecimalToStr(supplyAndSignVo.getSignPlanArea(),2));
                supplyAndSignVo.setSignAvgPlanPrice(NumberUtils.updateBigAccuracy(supplyAndSignVo.getSignAvgPlanPrice(),0));
                supplyAndSignVo.setSignPlanPrice(NumberUtils.priceToWanAndMicrometer(supplyAndSignVo.getSignPlanPrice()));
                supplyAndSignVo.setSignActualNum(NumberUtils.updateBigAccuracy(supplyAndSignVo.getSignActualNum(),2));
                supplyAndSignVo.setSignActualArea(NumberUtils.accuracyBigDecimalToStr(supplyAndSignVo.getSignActualArea(),2));
                supplyAndSignVo.setSignAvgActualPrice(NumberUtils.updateBigAccuracy(supplyAndSignVo.getSignAvgActualPrice(),0));
                supplyAndSignVo.setSignActualPrice(NumberUtils.priceToWanAndMicrometer(supplyAndSignVo.getSignActualPrice()));

                List<MonthSignVo> monthSignVoList = vo.getMonthSignVo();
                for (MonthSignVo monthSignVo:monthSignVoList){
                    monthSignVo.setEarlyNum(NumberUtils.updateBigAccuracy(monthSignVo.getEarlyNum(),2));
                    monthSignVo.setEarlyArea(NumberUtils.accuracyBigDecimalToStr(monthSignVo.getEarlyArea(),2));
                    monthSignVo.setAvgEarlyPrice(NumberUtils.updateBigAccuracy(monthSignVo.getAvgEarlyPrice(),0));
                    monthSignVo.setEarlyPrice(NumberUtils.priceToWanAndMicrometer(monthSignVo.getEarlyPrice()));
                    monthSignVo.setEarlySignPlanNum(NumberUtils.updateBigAccuracy(monthSignVo.getEarlySignPlanNum(),2));
                    monthSignVo.setEarlySignPlanArea(NumberUtils.accuracyBigDecimalToStr(monthSignVo.getEarlySignPlanArea(),2));
                    monthSignVo.setEarlyAvgSignPlanPrice(NumberUtils.updateBigAccuracy(monthSignVo.getEarlyAvgSignPlanPrice(),0));
                    monthSignVo.setEarlySignPlanPrice(NumberUtils.priceToWanAndMicrometer(monthSignVo.getEarlySignPlanPrice()));
                    monthSignVo.setEarlySignActualNum(NumberUtils.updateBigAccuracy(monthSignVo.getEarlySignActualNum(),2));
                    monthSignVo.setEarlySignActualArea(NumberUtils.accuracyBigDecimalToStr(monthSignVo.getEarlySignActualArea(),2));
                    monthSignVo.setEarlyAvgSignActualPrice(NumberUtils.updateBigAccuracy(monthSignVo.getEarlyAvgSignActualPrice(),0));
                    monthSignVo.setEarlySignActualPrice(NumberUtils.priceToWanAndMicrometer(monthSignVo.getEarlySignActualPrice()));
                    monthSignVo.setSupplyPlanNum(NumberUtils.updateBigAccuracy(monthSignVo.getSupplyPlanNum(),2));
                    monthSignVo.setSupplyPlanArea(NumberUtils.accuracyBigDecimalToStr(monthSignVo.getSupplyPlanArea(),2));
                    monthSignVo.setSupplyAvgPlanPrice(NumberUtils.updateBigAccuracy(monthSignVo.getSupplyAvgPlanPrice(),0));
                    monthSignVo.setSupplyPlanPrice(NumberUtils.priceToWanAndMicrometer(monthSignVo.getSupplyPlanPrice()));
                    monthSignVo.setSupplyActualNum(NumberUtils.updateBigAccuracy(monthSignVo.getSupplyActualNum(),2));
                    monthSignVo.setSupplyActualArea(NumberUtils.accuracyBigDecimalToStr(monthSignVo.getSupplyActualArea(),2));
                    monthSignVo.setSupplyAvgActualPrice(NumberUtils.updateBigAccuracy(monthSignVo.getSupplyAvgActualPrice(),0));
                    monthSignVo.setSupplyActualPrice(NumberUtils.priceToWanAndMicrometer(monthSignVo.getSupplyActualPrice()));
                    monthSignVo.setSupplySignPlanNum(NumberUtils.updateBigAccuracy(monthSignVo.getSupplySignPlanNum(),2));
                    monthSignVo.setSupplySignPlanArea(NumberUtils.accuracyBigDecimalToStr(monthSignVo.getSupplySignPlanArea(),2));
                    monthSignVo.setSupplyAvgSignPlanPrice(NumberUtils.updateBigAccuracy(monthSignVo.getSupplyAvgSignPlanPrice(),0));
                    monthSignVo.setSupplySignPlanPrice(NumberUtils.priceToWanAndMicrometer(monthSignVo.getSupplySignPlanPrice()));
                    monthSignVo.setSupplySignActualNum(NumberUtils.updateBigAccuracy(monthSignVo.getSupplySignActualNum(),2));
                    monthSignVo.setSupplySignActualArea(NumberUtils.accuracyBigDecimalToStr(monthSignVo.getSupplySignActualArea(),2));
                    monthSignVo.setSupplyAvgSignActualPrice(NumberUtils.updateBigAccuracy(monthSignVo.getSupplyAvgSignActualPrice(),0));
                    monthSignVo.setSupplySignActualPrice(NumberUtils.priceToWanAndMicrometer(monthSignVo.getSupplySignActualPrice()));
                    monthSignVo.setSyntheticalAvailableNum(NumberUtils.updateBigAccuracy(monthSignVo.getSyntheticalAvailableNum(),2));
                    monthSignVo.setSyntheticalAvailableArea(NumberUtils.accuracyBigDecimalToStr(monthSignVo.getSyntheticalAvailableArea(),2));
                    monthSignVo.setSyntheticalAvailableAvgPrice(NumberUtils.updateBigAccuracy(monthSignVo.getSyntheticalAvailableAvgPrice(),0));
                    monthSignVo.setSyntheticalAvailablePrice(NumberUtils.priceToWanAndMicrometer(monthSignVo.getSyntheticalAvailablePrice()));
                    monthSignVo.setSyntheticalSignPlanNum(NumberUtils.updateBigAccuracy(monthSignVo.getSyntheticalSignPlanNum(),2));
                    monthSignVo.setSyntheticalSignPlanArea(NumberUtils.accuracyBigDecimalToStr(monthSignVo.getSyntheticalSignPlanArea(),2));
                    monthSignVo.setSyntheticalAvgSignPlanPrice(NumberUtils.updateBigAccuracy(monthSignVo.getSyntheticalAvgSignPlanPrice(),0));
                    monthSignVo.setSyntheticalSignPlanPrice(NumberUtils.priceToWanAndMicrometer(monthSignVo.getSyntheticalSignPlanPrice()));
                    monthSignVo.setSyntheticalSignActualNum(NumberUtils.updateBigAccuracy(monthSignVo.getSyntheticalSignActualNum(),2));
                    monthSignVo.setSyntheticalSignActualArea(NumberUtils.accuracyBigDecimalToStr(monthSignVo.getSyntheticalSignActualArea(),2));
                    monthSignVo.setSyntheticalAvgSignActualPrice(NumberUtils.updateBigAccuracy(monthSignVo.getSyntheticalAvgSignActualPrice(),0));
                    monthSignVo.setSyntheticalSignActualPrice(NumberUtils.priceToWanAndMicrometer(monthSignVo.getSyntheticalSignActualPrice()));
                }

                YearSignVo yearSignVo = vo.getYearSignVo();
                yearSignVo.setEarlyNum(NumberUtils.updateBigAccuracy(yearSignVo.getEarlyNum(),2));
                yearSignVo.setEarlyArea(NumberUtils.accuracyBigDecimalToStr(yearSignVo.getEarlyArea(),2));
                yearSignVo.setEarlyAvgPrice(NumberUtils.updateBigAccuracy(yearSignVo.getEarlyAvgPrice(),0));
                yearSignVo.setEarlyPrice(NumberUtils.priceToWanAndMicrometer(yearSignVo.getEarlyPrice()));
                yearSignVo.setEarlySignActualNum(NumberUtils.updateBigAccuracy(yearSignVo.getEarlySignActualNum(),2));
                yearSignVo.setEarlySignActualArea(NumberUtils.accuracyBigDecimalToStr(yearSignVo.getEarlySignActualArea(),2));
                yearSignVo.setEarlySignActualAvgPrice(NumberUtils.updateBigAccuracy(yearSignVo.getEarlySignActualAvgPrice(),0));
                yearSignVo.setEarlySignActualPrice(NumberUtils.priceToWanAndMicrometer(yearSignVo.getEarlySignActualPrice()));
                yearSignVo.setSupplyPlanNum(NumberUtils.updateBigAccuracy(yearSignVo.getSupplyPlanNum(),2));
                yearSignVo.setSupplyPlanArea(NumberUtils.accuracyBigDecimalToStr(yearSignVo.getSupplyPlanArea(),2));
                yearSignVo.setSupplyPlanAvgPrice(NumberUtils.updateBigAccuracy(yearSignVo.getSupplyPlanAvgPrice(),0));
                yearSignVo.setSupplyPlanPrice(NumberUtils.priceToWanAndMicrometer(yearSignVo.getSupplyPlanPrice()));
                yearSignVo.setSupplyActualNum(NumberUtils.updateBigAccuracy(yearSignVo.getSupplyActualNum(),2));
                yearSignVo.setSupplyActualArea(NumberUtils.accuracyBigDecimalToStr(yearSignVo.getSupplyActualArea(),2));
                yearSignVo.setSupplyActualAvgPrice(NumberUtils.updateBigAccuracy(yearSignVo.getSupplyActualAvgPrice(),0));
                yearSignVo.setSupplyActualPrice(NumberUtils.priceToWanAndMicrometer(yearSignVo.getSupplyActualPrice()));
                yearSignVo.setSupplySignActualNum(NumberUtils.updateBigAccuracy(yearSignVo.getSupplySignActualNum(),2));
                yearSignVo.setSupplySignActualArea(NumberUtils.accuracyBigDecimalToStr(yearSignVo.getSupplySignActualArea(),2));
                yearSignVo.setSupplySignActualAvgPrice(NumberUtils.updateBigAccuracy(yearSignVo.getSupplySignActualAvgPrice(),0));
                yearSignVo.setSupplySignActualPrice(NumberUtils.priceToWanAndMicrometer(yearSignVo.getSupplySignActualPrice()));
                yearSignVo.setSyntheticalAvailableNum(NumberUtils.updateBigAccuracy(yearSignVo.getSyntheticalAvailableNum(),2));
                yearSignVo.setSyntheticalAvailableArea(NumberUtils.accuracyBigDecimalToStr(yearSignVo.getSyntheticalAvailableArea(),2));
                yearSignVo.setSyntheticalAvailableAvgPrice(NumberUtils.updateBigAccuracy(yearSignVo.getSyntheticalAvailableAvgPrice(),0));
                yearSignVo.setSyntheticalAvailablePrice(NumberUtils.priceToWanAndMicrometer(yearSignVo.getSyntheticalAvailablePrice()));
                yearSignVo.setSyntheticalSignPlanNum(NumberUtils.updateBigAccuracy(yearSignVo.getSyntheticalSignPlanNum(),2));
                yearSignVo.setSyntheticalSignPlanArea(NumberUtils.accuracyBigDecimalToStr(yearSignVo.getSyntheticalSignPlanArea(),2));
                yearSignVo.setSyntheticalSignPlanAvgPrice(NumberUtils.updateBigAccuracy(yearSignVo.getSyntheticalSignPlanAvgPrice(),0));
                yearSignVo.setSyntheticalSignPlanPrice(NumberUtils.priceToWanAndMicrometer(yearSignVo.getSyntheticalSignPlanPrice()));
                yearSignVo.setSyntheticalSignActualNum(NumberUtils.updateBigAccuracy(yearSignVo.getSyntheticalSignActualNum(),2));
                yearSignVo.setSyntheticalSignActualArea(NumberUtils.accuracyBigDecimalToStr(yearSignVo.getSyntheticalSignActualArea(),2));
                yearSignVo.setSyntheticalSignActualAvgPrice(NumberUtils.updateBigAccuracy(yearSignVo.getSyntheticalSignActualAvgPrice(),0));
                yearSignVo.setSyntheticalSignActualPrice(NumberUtils.priceToWanAndMicrometer(yearSignVo.getSyntheticalSignActualPrice()));

                List<QuarterSignVo> quarterSignVoList = vo.getQuarterSignVo();
                for (QuarterSignVo quarterSignVo :quarterSignVoList){
                    quarterSignVo.setEarlyNum(NumberUtils.updateBigAccuracy(quarterSignVo.getEarlyNum(),2));
                    quarterSignVo.setEarlyArea(NumberUtils.accuracyBigDecimalToStr(quarterSignVo.getEarlyArea(),2));
                    quarterSignVo.setEarlyAvgPrice(NumberUtils.updateBigAccuracy(quarterSignVo.getEarlyAvgPrice(),0));
                    quarterSignVo.setEarlyPrice(NumberUtils.priceToWanAndMicrometer(quarterSignVo.getEarlyPrice()));
                    quarterSignVo.setSupplyNum(NumberUtils.updateBigAccuracy(quarterSignVo.getSupplyNum(),2));
                    quarterSignVo.setSupplyArea(NumberUtils.accuracyBigDecimalToStr(quarterSignVo.getSupplyArea(),2));
                    quarterSignVo.setSupplyAvgPrice(NumberUtils.updateBigAccuracy(quarterSignVo.getSupplyAvgPrice(),0));
                    quarterSignVo.setSupplyPrice(NumberUtils.priceToWanAndMicrometer(quarterSignVo.getSupplyPrice()));
                    quarterSignVo.setAvailableNum(NumberUtils.updateBigAccuracy(quarterSignVo.getAvailableNum(),2));
                    quarterSignVo.setAvailableArea(NumberUtils.accuracyBigDecimalToStr(quarterSignVo.getAvailableArea(),2));
                    quarterSignVo.setAvailableAvgPrice(NumberUtils.updateBigAccuracy(quarterSignVo.getAvailableAvgPrice(),0));
                    quarterSignVo.setAvailablePrice(NumberUtils.priceToWanAndMicrometer(quarterSignVo.getAvailablePrice()));
                    quarterSignVo.setSignPlanNum(NumberUtils.updateBigAccuracy(quarterSignVo.getSignPlanNum(),2));
                    quarterSignVo.setSignPlanArea(NumberUtils.accuracyBigDecimalToStr(quarterSignVo.getSignPlanArea(),2));
                    quarterSignVo.setSignAvgPlanPrice(NumberUtils.updateBigAccuracy(quarterSignVo.getSignAvgPlanPrice(),0));
                    quarterSignVo.setSignPlanPrice(NumberUtils.priceToWanAndMicrometer(quarterSignVo.getSignPlanPrice()));
                }

                List<YearTotalVo> yearTotalVoList = vo.getYearTotalVo();
                for (YearTotalVo yearTotalVo : yearTotalVoList){
                    yearTotalVo.setEarlyNum(NumberUtils.updateBigAccuracy(yearTotalVo.getEarlyNum(),2));
                    yearTotalVo.setEarlyArea(NumberUtils.accuracyBigDecimalToStr(yearTotalVo.getEarlyArea(),2));
                    yearTotalVo.setEarlyAvgPrice(NumberUtils.updateBigAccuracy(yearTotalVo.getEarlyAvgPrice(),0));
                    yearTotalVo.setEarlyPrice(NumberUtils.priceToWanAndMicrometer(yearTotalVo.getEarlyPrice()));
                    yearTotalVo.setSupplyNum(NumberUtils.updateBigAccuracy(yearTotalVo.getSupplyNum(),2));
                    yearTotalVo.setSupplyArea(NumberUtils.accuracyBigDecimalToStr(yearTotalVo.getSupplyArea(),2));
                    yearTotalVo.setSupplyAvgPrice(NumberUtils.updateBigAccuracy(yearTotalVo.getSupplyAvgPrice(),0));
                    yearTotalVo.setSupplyPrice(NumberUtils.priceToWanAndMicrometer(yearTotalVo.getSupplyPrice()));
                    yearTotalVo.setAvailableNum(NumberUtils.updateBigAccuracy(yearTotalVo.getAvailableNum(),2));
                    yearTotalVo.setAvailableArea(NumberUtils.accuracyBigDecimalToStr(yearTotalVo.getAvailableArea(),2));
                    yearTotalVo.setAvailableAvgPrice(NumberUtils.updateBigAccuracy(yearTotalVo.getAvailableAvgPrice(),0));
                    yearTotalVo.setAvailablePrice(NumberUtils.priceToWanAndMicrometer(yearTotalVo.getAvailablePrice()));
                    yearTotalVo.setSignPlanNum(NumberUtils.updateBigAccuracy(yearTotalVo.getSignPlanNum(),2));
                    yearTotalVo.setSignPlanArea(NumberUtils.accuracyBigDecimalToStr(yearTotalVo.getSignPlanArea(),2));
                    yearTotalVo.setSignAvgPlanPrice(NumberUtils.updateBigAccuracy(yearTotalVo.getSignAvgPlanPrice(),0));
                    yearTotalVo.setSignPlanPrice(NumberUtils.priceToWanAndMicrometer(yearTotalVo.getSignPlanPrice()));
                }
            }
        }
    }

    /**
     * 刷新指定项目数据
     * @param projectId
     * @param yearMonth
     */
    @Override
    public void refreshProject(String projectId, String yearMonth) {


        Integer yearMonthInt = Integer.valueOf(yearMonth.replace("-",""));
        dmDmPlanSignMonthMapper.delByProjectIdAndSnapshootYearMonth(projectId,yearMonthInt);
        dmDmPlanSignYearMapper.delByProjectIdAndSnapshootYearMonth(projectId,yearMonthInt);
        //查询项目指定年月全盘最新的版本集合
        List<String> versionIdList = signPlanVersionService.getOverallSignVersionList(projectId,yearMonth);
        if(CollectionUtils.isEmpty(versionIdList)){
            return;
        }
        //刷新供销综合底表
        toSign(versionIdList,yearMonth);
    }


    /**
     * 保存系统日志
     */
    private boolean saveLog(LogEventEnum logEventEnum,String module,String title,String content) {
        SysLogBO bo = new SysLogBO();
        bo.setEvent(logEventEnum);
        bo.setSource(LogSrcEnum.PC);
        bo.setModule(module);
        bo.setTitle(title);
        bo.setContent(content);
        bo.setType(LogTypeEnum.ONE.getKey());
        bo.setIsSuccess(IsSuccessEnum.SUCCESS.getKey());
        return sysLogService.add(bo,Constants.SYS);
    }

    //层级排序
    public List<DmAnalyticalVo> sortList(List<DmAnalyticalVo> resultList){
        List<DmAnalyticalVo> sortList =  resultList.parallelStream().sorted((a, b) -> {

            //区域
            String aRegionName = StrUtils.nvl(a.getBusinessDivisionName());
            String bRegionName = StrUtils.nvl(b.getBusinessDivisionName());
            if (!aRegionName.equals(bRegionName)) {
                return aRegionName.compareTo(bRegionName);
            }
            //城市公司
            String aCityName = StrUtils.nvl(a.getCityCompanyName());
            String bCityName = StrUtils.nvl(b.getCityCompanyName());
            if (!aCityName.equals(bCityName)) {
                return aCityName.compareTo(bCityName);
            }
            //项目
            String aProjectName = StrUtils.nvl(a.getProjectName());
            String bProjectName = StrUtils.nvl(b.getProjectName());
            if (!aProjectName.equals(bProjectName)) {
                return aProjectName.compareTo(bProjectName);
            }

            //分期
            String[] aProjectfNameArr = StrUtils.nvl(a.getStageName()).split("期");
            String[] bProjectfNameArr = StrUtils.nvl(b.getStageName()).split("期");

            String aProjectfName = NumberEnum.getKeyByValue(aProjectfNameArr[0]) == null ? "0" : NumberEnum.getKeyByValue(aProjectfNameArr[0]);
            String bProjectfName = NumberEnum.getKeyByValue(bProjectfNameArr[0]) == null ? "0" : NumberEnum.getKeyByValue(bProjectfNameArr[0]);
            if (!aProjectfName.equals(bProjectfName)) {
                return aProjectfName == null ? 1 : bProjectfName == null ? -1 : Integer.valueOf(aProjectfName) - Integer.valueOf(bProjectfName);
            }

            //组团
            String[] aGroupNameArr = StrUtils.nvl(a.getGroupName()).split("组团");
            String[] bGroupNameArr = StrUtils.nvl(b.getGroupName()).split("组团");

            if (aGroupNameArr[0].equals("车位")) {
                aGroupNameArr[0] = "10000000";
            }
            if (bGroupNameArr[0].equals("车位")) {
                bGroupNameArr[0] = "10000000";
            }

            String aGroupName = NumberEnum.getKeyByValue(aGroupNameArr[0]) == null ? "0" : NumberEnum.getKeyByValue(aGroupNameArr[0]);
            String bGroupName = NumberEnum.getKeyByValue(bGroupNameArr[0]) == null ? "0" : NumberEnum.getKeyByValue(bGroupNameArr[0]);
            if (!aGroupName.equals(bGroupName)) {
                return aGroupName == null ? 1 : bGroupName == null ? -1 : Integer.valueOf(aGroupName) - Integer.valueOf(bGroupName);
            }

            //业态
            String aProProductName = StrUtils.nvl(a.getProProductName());
            String bProProductName = StrUtils.nvl(b.getProProductName());
            if (!aProProductName.equals(bProProductName)) {
                return aProProductName.compareTo(bProProductName);
            }

            //产品构成
//            String aProductName = StrUtils.nvl(a.getProductName());
//            String bProductName = StrUtils.nvl(b.getProductName());
//            if (!aProductName.equals(bProductName)) {
//                return aProductName.compareTo(bProductName);
//            }
            return 0;
        }).collect(Collectors.toList());
        return sortList;
    }
}
